前端模塊化之旅(二):CommonJS、AMD和CMD

前端模塊化之旅二.jpg

繼續(xù)前篇,各種模塊化規(guī)范開始推出,其中比較突出的是服務(wù)器端的 CommonJS 規(guī)范,它是 Nood.JS 在實(shí)踐中推出的,也是首先采用 JS 模塊化概念的語言,跳出了瀏覽器;進(jìn)而出現(xiàn)了瀏覽器環(huán)境的模塊化方案 AMD和CMD。

CommonJS Modules/1.0

CommonJS 規(guī)范是服務(wù)器端的模塊化的規(guī)范,是 Nood.js 在實(shí)踐中推出的,Nood.js 也是首先采用 js 模塊化的;

它規(guī)定一個(gè)單獨(dú)的文件就是一個(gè)模塊,一個(gè)模塊中存在一個(gè)自由變量 require,這是個(gè)函數(shù),用于加載模塊:

  • 這個(gè) require 函數(shù)接受一個(gè)模塊標(biāo)識符,返回外部模塊所輸出的 API;
  • 如果出現(xiàn)依賴閉環(huán)(dependency cycle),那么外部模塊在被它的傳遞依賴(transitive dependencies)所 require 的時(shí)候可能并沒有執(zhí)行完成;在這種情況下,"require"返回的對象必須至少包含此外部模塊在調(diào)用require函數(shù)(會進(jìn)入當(dāng)前模塊執(zhí)行環(huán)境)之前就已經(jīng)準(zhǔn)備完畢的輸出。
  • 如果請求的模塊不能返回,那么"require"必須拋出一個(gè)錯(cuò)誤。

在一個(gè)模塊中,會存在一個(gè)名為 exports 的自由變量,這是一個(gè)對象,模塊可以在執(zhí)行的時(shí)候把自身的API加入到其中,用于定義模塊,導(dǎo)出給其他地方使用;

exports 對象是輸出模塊變量的唯一方式。

參照下面的一個(gè)例子:

//math.js
exports.add = function(a,b){
    var c = a + b;
    return c;
}

//index.js
var add = require('math').add;//
console.log(add(1,1));//2

math.js中將 add 函數(shù)綁定到模塊中的 exports 對象中,之后在 index.js 模塊中用 require 方法加載了 math.js 模塊,并調(diào)用該模塊中的 add 函數(shù)。

AMD

Asynchronous Module Definition,即異步的模塊定義,是瀏覽器端的模塊化規(guī)范,是 RequireJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出。

與服務(wù)器端的模塊化規(guī)范 CommonJS 不同,AMD 的模塊加載是異步的,因?yàn)槭菫g覽器端,所以勢必要是異步的(瀏覽器同步加載模塊會導(dǎo)致性能、可用性、調(diào)試和跨域訪問等問題)。因?yàn)槟K異步加載時(shí)不會影響后面程序的執(zhí)行,前面總結(jié)過 js 異步的情況,依賴某些模塊的語句均放置在回調(diào)函數(shù)中,等待模塊加載完成后再執(zhí)行;

AMD 規(guī)范只定義了一個(gè)函數(shù) define ,是一個(gè)全局變量,如下定義一個(gè)模塊的語法:

define(id?, dependencies?, factory);
  • id:模塊的名字,如果沒有提供該參數(shù),模塊的名字應(yīng)該默認(rèn)為模塊加載器請求的指定腳本的名字;

  • dependencies:模塊的依賴,已被模塊定義的模塊標(biāo)識的數(shù)組字面量。依賴參數(shù)是可選的,如果忽略此參數(shù),它應(yīng)該默認(rèn)為 ["require", "exports", "module"]。然而,如果工廠方法的長度屬性小于3,加載器會選擇以函數(shù)的長度屬性指定的參數(shù)個(gè)數(shù)調(diào)用工廠方法。

  • factory:模塊的工廠函數(shù),模塊初始化要執(zhí)行的函數(shù)或?qū)ο蟆H绻麨楹瘮?shù),它應(yīng)該只被執(zhí)行一次。如果是對象,此對象應(yīng)該為模塊的輸出值。

參照下面的一個(gè)例子:

define('myModule',['jQuery','types/Employee'],function($,Employee){//定義模塊myModule,引入依賴jQuery,types/Employee
     function Programmer(){
            //do something
        };
        Programmer.prototype = new Employee();
        return Programmer;  //return Constructor
})

CMD

Common Module Definition,即通用模塊定義,是瀏覽器端的模塊化規(guī)范,是 SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出。

如下定義一個(gè)模塊的語法:

define(factory)
  • factory 為函數(shù)時(shí),表示是模塊的構(gòu)造方法。執(zhí)行該構(gòu)造方法,可以得到模塊向外提供的接口。factory 方法在執(zhí)行時(shí),默認(rèn)會傳入三個(gè)參數(shù):require、exports 和 module.

AMD 是依賴關(guān)系前置,提前執(zhí)行;CMD 是類似于 CommonJS 那樣 按需加載,延遲執(zhí)行

//CMD recommanded
define(function(require, exports, module){
    var a = require('a');
    a.doSomething();
    var b = require('b');
    b.doSomething();    // 依賴就近,延遲執(zhí)行
});

//AMD recommanded
define(['a', 'b'], function(a, b){
    a.doSomething();    // 依賴前置,提前執(zhí)行
    b.doSomething();
});

明顯看出和 AMD 不同,模塊定義時(shí)已不用立馬引入依賴,而是運(yùn)行到需要時(shí)候再加載,根據(jù)順序執(zhí)行,這樣更像是 CommonJS 的風(fēng)格,讓人感覺也像是同步加載似的。但實(shí)際上 CMD 內(nèi)部處理是對文件做了一個(gè)詞法的解析,在還沒執(zhí)行的時(shí)候,解析出所需的依賴,并不是真正的同步。


參考:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容