摘要:來(lái)源于阿賢博客模塊化今天給大家寫一篇關(guān)于前端模塊化開(kāi)發(fā)知識(shí)點(diǎn)。前端模塊化開(kāi)發(fā)那點(diǎn)歷史模塊化是指在解決某個(gè)復(fù)雜混雜問(wèn)題時(shí),依照一種分類的思維把問(wèn)題進(jìn)行系統(tǒng)性的分解以之處理。
來(lái)源于:阿賢博客
javascript模塊化今天給大家寫一篇關(guān)于前端模塊化開(kāi)發(fā)知識(shí)點(diǎn)。
前端模塊化開(kāi)發(fā)那點(diǎn)歷史
模塊化:
是指在解決某個(gè)復(fù)雜、混雜問(wèn)題時(shí),依照一種分類的思維把問(wèn)題進(jìn)行系統(tǒng)性的分解以之處理。模塊化是一種處理復(fù)雜系統(tǒng)分解為代碼結(jié)構(gòu)更合理,可維護(hù)性更高的可管理的模塊的方式。
模塊化是軟件系統(tǒng)的屬性,這個(gè)系統(tǒng)被分解為一組高內(nèi)聚,低耦合的模塊。那么在理想狀態(tài)下我們只需要完成自己部分的核心業(yè)務(wù)邏輯代碼,其他方面的依賴可以通過(guò)直接加載被人已經(jīng)寫好模塊進(jìn)行使用即可。
模塊化系統(tǒng)所必須的能力:
定義封裝的模塊。
定義新模塊對(duì)其他模塊的依賴。
可對(duì)其他模塊的引入支持。
好了,思想有了,那么總要有點(diǎn)什么來(lái)建立一個(gè)模塊化的規(guī)范制度吧,不然各式各樣的模塊加載方式只會(huì)將局?jǐn)嚨酶鼮榛靵y。那么在JavaScript中出現(xiàn)了一些非傳統(tǒng)模塊開(kāi)發(fā)方式的規(guī)范 CommonJS的模塊規(guī)范,AMD(Asynchronous Module Definition),CMD(Common Module Definition)等。
為了建立一個(gè)模塊化的規(guī)范制度、模塊加載方式。在JavaScript中出現(xiàn)了一些非傳統(tǒng)模塊開(kāi)發(fā)方式的規(guī)范 CommonJS的模塊規(guī)范,AMD(Asynchronous Module Definition)、CMD(Common Module Definition)、ES6模塊誕生了。AMD規(guī)范(與Requirejs)
AMD(Asynchronous Module Definition)異步模塊定義,所有的模塊將被異步加載,模塊加載不影響后面語(yǔ)句運(yùn)行。所有依賴這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行。
AMD規(guī)范定義了一個(gè)自由變量或者說(shuō)是全局變量 define 的函數(shù)。
define( id?, dependencies?, factory );AMD規(guī)范
第一個(gè)參數(shù) id 為字符串類型,表示了模塊標(biāo)識(shí),為可選參數(shù)。若不存在則模塊標(biāo)識(shí)應(yīng)該默認(rèn)定義為在加載器中被請(qǐng)求腳本的標(biāo)識(shí)。如果存在,那么模塊標(biāo)識(shí)必須為頂層的或者一個(gè)絕對(duì)的標(biāo)識(shí)。
第二個(gè)參數(shù),dependencies ,是一個(gè)當(dāng)前模塊依賴的,已被模塊定義的模塊標(biāo)識(shí)的數(shù)組字面量。
第三個(gè)參數(shù),factory,是一個(gè)需要進(jìn)行實(shí)例化的函數(shù)或者一個(gè)對(duì)象。
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){ export.verb = function(){ return beta.verb(); // or: return require("beta").verb(); } });
define(["alpha"], function( alpha ){ return { verb : function(){ return alpha.verb() + 1 ; } } });
define( { add : function( x, y ){ return x + y ; } } );require();
require API
在 AMD 規(guī)范中的 require 函數(shù)與一般的 CommonJS中的 require 不同。由于動(dòng)態(tài)檢測(cè)依賴關(guān)系使加載異步,對(duì)于基于回調(diào)的 require 需求強(qiáng)烈。
局部的 require 需要在AMD模式中的 define 工廠函數(shù)中傳入 require。
define( ["require"], function( require ){ // ... } ); or: define( function( require, exports, module ){ // ... } );
局部的 require 需要其他特定的 API 來(lái)實(shí)現(xiàn)。
全局的 require 函數(shù)是唯一全局作用域下的變量,像 define一樣。全局的 require 并不是規(guī)范要求的,但是如果實(shí)現(xiàn)全局的 require函數(shù),那么其需要具有與局部 require 函數(shù) 一樣的以下的限定:
1. 模塊標(biāo)識(shí)視為絕對(duì)的,而不是相對(duì)的對(duì)應(yīng)另一個(gè)模塊標(biāo)識(shí)。
2. 只有在異步情況下,require的回調(diào)方式才被用來(lái)作為交互操作使用。因?yàn)樗豢赡茉谕降那闆r下通過(guò) require(String) 從頂層加載模塊。
依賴相關(guān)的API會(huì)開(kāi)始模塊加載。如果需要有互操作的多個(gè)加載器,那么全局的 reqiure 應(yīng)該被加載頂層模塊來(lái)代替。
require(String) define( function( require ){ var a = require("a"); // 加載模塊a } ); require(Array, Function) define( function( require ){ require( ["a", "b"], function( a,b ){ // 加載模塊a b 使用 // 依賴 a b 模塊的運(yùn)行代碼 } ); } ); require.toUrl( Url ) define( function( require ){ var temp = require.toUrl("./temp/a.html"); // 加載頁(yè)面 } );RequireJS
官網(wǎng)
API
API 中文
RequireJS 是一個(gè)前端的模塊化管理的工具庫(kù),遵循AMD規(guī)范,它的作者就是AMD規(guī)范的創(chuàng)始人 James Burke。
頁(yè)面頂層
defined用于定義模塊,RequireJS要求每個(gè)模塊均放在獨(dú)立的文件之中。按照是否有依賴其他模塊的情況分為獨(dú)立模塊和非獨(dú)立模塊。
define({ method1: function(){}, method2: function(){} }); //等價(jià)于 define(function(){ return{ method1: function(){}, method2: function(){} } });
define([ "module1", "module2" ], function(m1, m2){ //代碼... }); //等價(jià)于 define( function( require ){ var m1 = require( "module1" ), m2 = require( "module2" ); //代碼... });
define 和 require 這兩個(gè)定義模塊,調(diào)用模塊的方法合稱為AMD模式,定義模塊清晰,不會(huì)污染全局變量,清楚的顯示依賴關(guān)系。AMD模式可以用于瀏覽器環(huán)境并且允許非同步加載模塊,也可以按需動(dòng)態(tài)加載模塊。
/*** **** require方法調(diào)用模塊 **** 在加載 foo 與 bar 兩個(gè)模塊之后執(zhí)行回調(diào)函數(shù)實(shí)現(xiàn)具體過(guò)程。 ***/ require( ["foo", "bar"], function( foo, bar ){ foo.func(); bar.func(); } ); /*** **** 在define定義模塊內(nèi)部進(jìn)行require調(diào)用模塊 ***/ define( function( require ){ var m1 = require( "module1" ), m2 = require( "module2" ); //代碼... });CMD規(guī)范(與Seajs)
在CMD中,一個(gè)模塊就是一個(gè)文件,格式為:define( factory );
[CMD模塊定義規(guī)范](https://github.com/seajs/seaj...)
全局函數(shù)define,用來(lái)定義模塊。
參數(shù) factory 可以是一個(gè)函數(shù),也可以為對(duì)象或者字符串。
當(dāng) factory 為對(duì)象、字符串時(shí),表示模塊的接口就是該對(duì)象、字符串。
define({ "foo": "bar" });
define("this is {{data}}.");
//表示模塊的構(gòu)造方法,執(zhí)行構(gòu)造方法便可以得到模塊向外提供的接口。 define( function(require, exports, module) { // 模塊代碼 });define( id?, deps?, factory );
define也可以接受兩個(gè)以上的參數(shù),字符串id為模塊標(biāo)識(shí),數(shù)組deps為模塊依賴:
define( "module", ["module1", "module2"], function( require, exports, module ){ // 模塊代碼 } );
其與 AMD 規(guī)范用法不同。
require 是 factory 的第一個(gè)參數(shù)。
require( id );
接受模塊標(biāo)識(shí)作為唯一的參數(shù),用來(lái)獲取其他模塊提供的接口:
define(function( require, exports ){ var a = require("./a"); a.doSomething(); });require.async( id, callback? );
require是同步往下執(zhí)行的,需要的異步加載模塊可以使用 require.async 來(lái)進(jìn)行加載:
define( function(require, exports, module) { require.async(".a", function(a){ a.doSomething(); }); });require.resolve( id )
可以使用模塊內(nèi)部的路徑機(jī)制來(lái)返回模塊路徑,不會(huì)加載模塊。
exports 是 factory 的第二個(gè)參數(shù),用來(lái)向外提供模塊接口。define(function( require, exports ){ exports.foo = "bar"; // 向外提供的屬性 exports.do = function(){}; // 向外提供的方法 }); //使用 return 直接向外提供接口。 define(function( require, exports ){ return{ foo : "bar", // 向外提供的屬性 do : function(){} // 向外提供的方法 } }); //簡(jiǎn)化為直接對(duì)象字面量的形式: define({ foo : "bar", // 向外提供的屬性 do : function(){} // 向外提供的方法 });module 是factory的第三個(gè)參數(shù),為一個(gè)對(duì)象,上面存儲(chǔ)了一些與當(dāng)前模塊相關(guān)聯(lián)的屬性與方法。
module.id 為模塊的唯一標(biāo)識(shí)。
module.uri 根據(jù)模塊系統(tǒng)的路徑解析規(guī)則得到模塊的絕對(duì)路徑。
module.dependencies 表示模塊的依賴。
module.exports 當(dāng)前模塊對(duì)外提供的接口。
官網(wǎng)文檔
倉(cāng)庫(kù)代碼
SeaJS API快速參考
官網(wǎng)(http://seajs.org/)已經(jīng)關(guān)閉。
其define 與 require 使用方式基本就是CMD規(guī)范中的示例。
sea.js 核心特征:
遵循CMD規(guī)范,與NodeJS般的書寫模塊代碼。
依賴自動(dòng)加載,配置清晰簡(jiǎn)潔。
兼容 Chrome 3+,F(xiàn)irefox 2+,Safari 3.2+,Opera 10+,IE 5.5+。
用來(lái)在頁(yè)面中加載一個(gè)或者多個(gè)模塊
// 加載一個(gè)模塊 seajs.use("./a"); // 加載模塊,加載完成時(shí)執(zhí)行回調(diào) seajs.use("./a",function(a){ a.doSomething(); }); // 加載多個(gè)模塊執(zhí)行回調(diào) seajs.use(["./a","./b"],function(a , b){ a.doSomething(); b.doSomething(); });AMD 與 CMD 區(qū)別
玉伯對(duì)于 AMD 與 CMD 區(qū)別的解釋:
AMD 是 RequireJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出。
CMD 是 SeaJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出。
類似的還有 CommonJS Modules/2.0 規(guī)范,是 BravoJS 在推廣過(guò)程中對(duì)模塊定義的規(guī)范化產(chǎn)出
對(duì)于依賴的模塊,AMD 是提前執(zhí)行,CMD 是延遲執(zhí)行。不過(guò) RequireJS 從 2.0 開(kāi)始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不同)。
CMD 推崇依賴就近,AMD 推崇依賴前置??创a:
// CMD define(function(require, exports, module) { var a = require("./a"); a.doSomething(); // 此處略去 100 行 var b = require("./b"); // 依賴可以就近書寫 b.doSomething(); // 代碼... }) // AMD 默認(rèn)推薦的是 define(["./a", "./b"], function(a, b) { // 依賴必須一開(kāi)始就寫好 a.doSomething(); // 此處略去 100 行 b.doSomething(); // 代碼... })
雖然 AMD 也支持 CMD 的寫法,同時(shí)還支持將 require 作為依賴項(xiàng)傳遞,但 RequireJS 的作者默認(rèn)是最喜歡上面的寫法,也是官方文檔里默認(rèn)的模塊定義寫法。
AMD 的 API 默認(rèn)是一個(gè)當(dāng)多個(gè)用,CMD 的 API 嚴(yán)格區(qū)分,推崇職責(zé)單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒(méi)有全局 require,而是根據(jù)模塊系統(tǒng)的完備性,提供 seajs.use 來(lái)實(shí)現(xiàn)模塊系統(tǒng)的加載啟動(dòng)。CMD 里,每個(gè) API 都簡(jiǎn)單純粹。
還有一些細(xì)節(jié)差異,具體看這個(gè)規(guī)范的定義就好,就不多說(shuō)了。
另外,SeaJS 和 RequireJS 的差異
UMDUMD
AMD、CMD、UMD 模塊
既然CommonJs和AMD風(fēng)格一樣流行,似乎缺少一個(gè)統(tǒng)一的規(guī)范。所以人們產(chǎn)生了這樣的需求,希望有支持兩種風(fēng)格的“通用”模式,于是通用模塊規(guī)范(UMD)誕生了。
(function (root, factory) { if (typeof define === "function" && define.amd) { // AMD define(["jquery"], factory); } else if (typeof exports === "object") { // Node, CommonJS之類的 module.exports = factory(require("jquery")); } else { // 瀏覽器全局變量(root 即 window) root.returnExports = factory(root.jQuery); } }(this, function ($) { // 方法 function myFunc(){}; // 暴露公共方法 return myFunc; })); //復(fù)雜、依賴了多個(gè)組件并且暴露多個(gè)方法 (function (root, factory) { if (typeof define === "function" && define.amd) { // AMD define(["jquery", "underscore"], factory); } else if (typeof exports === "object") { // Node, CommonJS之類的 module.exports = factory(require("jquery"), require("underscore")); } else { // 瀏覽器全局變量(root 即 window) root.returnExports = factory(root.jQuery, root._); } }(this, function ($, _) { // 方法 function a(){}; // 私有方法,因?yàn)樗鼪](méi)被返回 (見(jiàn)下面) function b(){}; // 公共方法,因?yàn)楸环祷亓? function c(){}; // 公共方法,因?yàn)楸环祷亓? // 暴露公共方法 return { b: b, c: c } }));ES6模塊
ES6
Module 的語(yǔ)法
ES6 模塊的設(shè)計(jì)思想,是盡量的靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。比如,CommonJS 模塊就是對(duì)象,輸入時(shí)必須查找對(duì)象屬性。
// ES6模塊 import { stat, exists, readFile } from "fs";
上面代碼的實(shí)質(zhì)是從fs模塊加載3個(gè)方法,其他方法不加載。這種加載稱為“編譯時(shí)加載”或者靜態(tài)加載,即 ES6 可以在編譯時(shí)就完成模塊加載。
ES6模塊好處不再需要UMD模塊格式了,將來(lái)服務(wù)器和瀏覽器都會(huì)支持 ES6 模塊格式。目前,通過(guò)各種工具庫(kù),其實(shí)已經(jīng)做到了這一點(diǎn)。
將來(lái)瀏覽器的新 API 就能用模塊格式提供,不再必須做成全局變量或者navigator對(duì)象的屬性。
不再需要對(duì)象作為命名空間(比如Math對(duì)象),未來(lái)這些功能可以通過(guò)模塊提供。
擴(kuò)展閱讀:AMD規(guī)范文檔
amdjs 的 require 接口文檔
amdjs 的接口文檔
RequireJS官網(wǎng)接口文檔
模塊系統(tǒng)
前端模塊化開(kāi)發(fā)的價(jià)值
前端模塊化開(kāi)發(fā)那點(diǎn)歷史
CMD 模塊定義規(guī)范
SeaJS API快速參考
從 CommonJS 到 Sea.js
RequireJS和AMD規(guī)范
CommonJS規(guī)范
JavaScript模塊化開(kāi)發(fā) - CommonJS規(guī)范
JavaScript模塊化開(kāi)發(fā) - AMD規(guī)范
Javascript模塊化編程1
Javascript模塊化編程2
知乎 AMD 和 CMD 的區(qū)別有哪些?
與 RequireJS 的異同
模塊化設(shè)計(jì)
模塊化
ES6
Module 的語(yǔ)法
來(lái)源于:阿賢博客
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103210.html
摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒(méi)想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...
摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開(kāi)源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開(kāi)源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...
摘要:并不是使用安裝的模塊我們就可以使用同樣的方式使用任何一個(gè)模塊,使用某種工具將這些模塊打包發(fā)布作為事實(shí)上的前端模塊化標(biāo)準(zhǔn),或可以出來(lái)解救我們。目前比較拿的出手的,也就是的模塊化,比如或者等等,分別可以使用和。 Teambition是一家追求卓越技術(shù)的公司,我們工程師都很Geek,我們使用了很多新潮的,開(kāi)源的技術(shù)。同時(shí)我們也貢獻(xiàn)了很多開(kāi)源的項(xiàng)目。我們希望能夠把一些技術(shù)經(jīng)驗(yàn)分享給大家。...
摘要:了解模塊化開(kāi)發(fā)思想如果有軟件工程背景,那么這一思想就是你自身就應(yīng)該掌握的。玉伯也發(fā)表過(guò)前端模塊化開(kāi)發(fā)的價(jià)值了解目前技術(shù),哪些和模塊化開(kāi)發(fā)沾邊開(kāi)發(fā)功能模塊的時(shí)候,可以采用的解決方案。 一、前言 現(xiàn)在javascript的流行,前端的代碼越來(lái)越復(fù)雜,所以我們需要軟件工程的思想來(lái)開(kāi)發(fā)前端。模塊化是必不可少的,這樣不僅能夠提高代碼的可維護(hù)性、可擴(kuò)展性以及魯棒性,更大的好處就是能夠提升整個(gè)團(tuán)隊(duì)的...
摘要:我是這一期的主持人黃子毅本期精讀的文章是。模塊化需要保證全局變量盡量干凈,目前為止的模塊化方案都沒(méi)有很好的做到這一點(diǎn)。精讀本次提出獨(dú)到觀點(diǎn)的同學(xué)有流形,黃子毅,蘇里約,,楊森,淡蒼,留影,精讀由此歸納。 這次是前端精讀期刊與大家第一次正式碰面,我們每周會(huì)精讀并分析若干篇精品好文,試圖討論出結(jié)論性觀點(diǎn)。沒(méi)錯(cuò),我們?cè)噲D通過(guò)觀點(diǎn)的碰撞,爭(zhēng)做無(wú)主觀精品好文的意見(jiàn)領(lǐng)袖。 我是這一期的主持人 ——...
摘要:前端工程化的演化。前端較為流行的單元測(cè)試,等自動(dòng)化測(cè)試自動(dòng)化測(cè)試是軟件通過(guò)模擬瀏覽器,對(duì)頁(yè)面進(jìn)行操作,判斷是否產(chǎn)生預(yù)想的效果。 前端工程化 ??前端工程化的概念在近些年來(lái)逐漸成為主流構(gòu)建大型web應(yīng)用不可或缺的一部分,在此我通過(guò)以下這三方面總結(jié)一下自己的理解。 為什么需要前端工程化。 前端工程化的演化。 怎么實(shí)現(xiàn)前端工程化。 為什么需要工程化 ??隨著近些年來(lái)前端技術(shù)的不斷發(fā)展,越...
閱讀 1483·2021-09-02 19:23
閱讀 1654·2021-08-11 11:19
閱讀 668·2019-08-30 15:55
閱讀 1677·2019-08-30 12:50
閱讀 2276·2019-08-30 11:23
閱讀 2210·2019-08-29 13:13
閱讀 1525·2019-08-28 18:13
閱讀 3367·2019-08-26 11:53