聊一聊CommonJS,Requirejs,SeaJS,AMD,CMD之間需要理清的關係

在學習js和使用js的過程中一定會使用到模塊化開發的思想。而提到模塊化就一定會提到CommenJS、RequireJS、AMD、CMD等名詞。下面我將根據自己查閱的資料梳理以下這幾個名詞背後的關聯。

首先上個圖,直觀的感受下這幾個名詞的關係:



commonjs是用在服務器端的,模塊的加載方式是同步的,如nodejs。
amd, cmd是用在瀏覽器端的,這兩種規範規定的模塊的加載方式是異步的,它們的對應的模塊加載器分別是requirejs和seajs。

其中,amd先提出,cmd是根據commonjs和amd基礎上提出的。 


CommonJS 

CommonJs 是服務器端模塊的規範,Node.js採用了這個規範。 

根據CommonJS規範,一個單獨的文件就是一個模塊。加載模塊使用require方法,該方法讀取一個文件並執行,最後返回文件內部的exports對象。 

例如: 
// foobar.js 

//私有變量 
var test = 123; 

//公有方法 
function foobar () { 

    this.foo = function () { 
        // do someing ... 
    } 
    this.bar = function () { 
        //do someing ... 
    } 


//exports對象上的方法和變量是公有的 
var foobar = new foobar(); 
exports.foobar = foobar; 

//require方法默認讀取js文件,所以可以省略js後綴 
var test = require('./boobar').foobar; 

test.bar(); 


CommonJS加載模塊是同步的,所以只有加載完成才能執行後面的操作。像Node.js主要用於服務器的編程,加載的模塊文件一般都已經存在本地硬盤,所以加載起來比較快,不用考慮異步加載的方式,所以CommonJS規範比較適用。但如果是瀏覽器環境,要從服務器加載模塊,這時就需要採用異步模式。所以就有了 AMD 和CMD 解決方案。 


AMD((Asynchromous Module Definition) 

AMD 是 RequireJS 在推廣過程中對模塊定義的規範化產出 

AMD異步加載模塊。它的模塊支持對象 函數 構造器 字符串 JSON等各種類型的模塊。 

適用AMD規範適用define方法定義模塊。 

//通過數組引入依賴 ,回調函數通過形參傳入依賴 
define(['someModule1', ‘someModule2’], function (someModule1, someModule2) { 

    function foo () { 
        /// someing 
        someModule1.test(); 
    } 

    return {foo: foo} 
}); 
AMD規範允許輸出模塊兼容CommonJS規範,這時define方法如下: 

define(function (require, exports, module) { 
     
    var reqModule = require("./someModule"); 
    requModule.test(); 
     
    exports.asplode = function () { 
        //someing 
    } 
}); 



CMD 

CMD是SeaJS 在推廣過程中對模塊定義的規範化產出 

CMD和AMD的區別有以下幾點: 

1.對於依賴的模塊AMD是提前執行,CMD是延遲執行。不過RequireJS從2.0開始,也改成可以延遲執行(根據寫法不同,處理方式不通過)。 

2.CMD推崇依賴就近,AMD推崇依賴前置。 
//AMD 
define(['./a','./b'], function (a, b) { 

    //依賴一開始就寫好 
    a.test(); 
    b.test(); 
}); 

//CMD 
define(function (requie, exports, module) { 
     
    //依賴可以就近書寫 
    var a = require('./a'); 
    a.test(); 
     
    ... 
    //軟依賴 
    if (status) { 
     
        var b = requie('./b'); 
        b.test(); 
    } 
}); 
雖然 AMD也支持CMD寫法,但依賴前置是官方文檔的默認模塊定義寫法。 

3.AMD的api默認是一個當多個用,CMD嚴格的區分推崇職責單一。例如:AMD裏require分全局的和局部的。CMD裏面沒有全局的 require,提供 seajs.use()來實現模塊系統的加載啓動。CMD裏每個API都簡單純粹。 

SeaJS 和 RequireJS的主要區別在此有解釋。


續:RequireJS及SeaJS與CommonJS的比較(嚴格意義上前兩者與後者不該放在一起比較,因爲前兩者是規範的具體實現而後者是一種規範)

RequireJS實現了AMD的API.

CommonJS是使用exports對象來定義模塊的一種方法,它定義了模塊的內容。簡單地實現一個CommonJS的定義就像下面這樣:

// someModule.js

exports.doSomething = function() { return "foo"; };

//otherModule.js

var someModule = require('someModule'); // in the vein of node

exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };

基本上CommonJS明確了你需要有一個require函數來獲取依賴,exports變量來輸出模塊的內容和一些用來獲取依賴的模塊標識符。CommonJS有多種實現,比如Node.js.

因爲CommonJS設計的時候沒有考慮瀏覽器,所以它不適合瀏覽器環境(我其實對這個不明確,但是這種說法到處都有,比如RequireJS官網)。所以我們得做一些工作來實現異步加載。

相反,RequireJS實現了AMD,它被設計用來適應瀏覽器環境。表面上看來,AMD開始是CommonJS輸出格式的副產品,而且最終進化出了自己的API。在AMD中出現的新東西是define函數,它允許模塊在加載依賴之前聲明它的依賴。例如定義可能就像下面這樣:

define('module/id/string', ['module', 'dependency', 'array'],

function(module, factory function) {

return ModuleContents;

});

因此CommonJS和AMD是Javascript模塊定義API的不同的實現,但是他們有相同的根源。AMD更適合瀏覽器,因爲它支持異步加載模塊依賴。RequireJS是AMD的一個實現,而且儘量保留了CommonJS的精神(主要是模塊標識符上)。更讓人混亂的是,RequireJS在實現AMD的同時,還提供了一個CommonJS包裹,這樣CommonJS模塊可以幾乎直接被RequireJS引入。

define(function(require, exports, module) {

var someModule = require('someModule'); // in the vein of node

exports.doSomethingElse = function() { return someModule.doSomething() + "bar"; };

});

參考資料:


PS.【續】部分採用了一篇博文,發文時找不到原文鏈接了。。。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章