CommonJS, AMD, CMD , es6模塊化

CommonJS

CommonJS是一種代碼書寫規(guī)范。
** 代表:node.js **

2009年,美國程序員Ryan Dahl創(chuàng)造了node.js項(xiàng)目,將javascript語言用于服務(wù)器端編程。

這標(biāo)志"Javascript模塊化編程"正式誕生。因?yàn)槔蠈?shí)說,在瀏覽器環(huán)境下,沒有模塊也不是特別大的問題,畢竟網(wǎng)頁程序的復(fù)雜性有限;但是在服務(wù)器端,一定要有模塊,與操作系統(tǒng)和其他應(yīng)用程序互動,否則根本沒法編程。

node.js的模塊系統(tǒng),就是參照CommonJS規(guī)范實(shí)現(xiàn)的。在CommonJS中,有一個全局性方法require(),用于加載模塊。假定有一個數(shù)學(xué)模塊math.js,就可以像下面這樣加載。

var math = require('math');

然后,就可以調(diào)用模塊提供的方法:

var math = require('math');
math.add(2,3); // 5

因?yàn)檫@個系列主要針對瀏覽器編程,不涉及node.js,所以對CommonJS就不多做介紹了。我們在這里只要知道,require()用于加載模塊就行了。

AMD (異步模塊定義)

AMD是"Asynchronous Module Definition"的縮寫,意思就是"異步模塊定義"。
** 代表:require.js **

頁面引入require.js文件

<script src="js/require.js" defer async="true" ></script>
<script src="js/require.js" data-main="js/main"></script>
// main.js
       require.config({
    baseUrl: "js/lib",
    paths: {
      "jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"
    }
  });

  require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // some code here
  });

基于commonJS規(guī)范的nodeJS出來以后,服務(wù)端的模塊概念已經(jīng)形成,很自然地,大家就想要客戶端模塊。而且最好兩者能夠兼容,一個模塊不用修改,在服務(wù)器和瀏覽器都可以運(yùn)行。但是,由于一個重大的局限,使得CommonJS規(guī)范不適用于瀏覽器環(huán)境。

var math = require('math');
math.add(2, 3);

第二行math.add(2, 3),在第一行require('math')之后運(yùn)行,因此必須等math.js加載完成。也就是說,如果加載時(shí)間很長,整個應(yīng)用就會停在那里等。您會注意到 require 是同步的。

這對服務(wù)器端不是一個問題,因?yàn)樗械哪K都存放在本地硬盤,可以同步加載完成,等待時(shí)間就是硬盤的讀取時(shí)間。但是,對于瀏覽器,這卻是一個大問題,因?yàn)槟K都放在服務(wù)器端,等待時(shí)間取決于網(wǎng)速的快慢,可能要等很長時(shí)間,瀏覽器處于"假死"狀態(tài)。

因此,瀏覽器端的模塊,不能采用"同步加載"(synchronous),只能采用"異步載"(asynchronous)。這就是AMD規(guī)范誕生的背景。

CMD(通用模塊定義)

CMD 推崇依賴就近,AMD 推崇依賴前置。

// CMD
defined (function (require, exports, module) {
  var a = requrie('./a')
  a.doSomething()
  // 此處略去 100行
  var b = require('./b') // 依賴可以就近書寫
   b.doSomething()
    ...
})

// AMD
define(['./a' , './b'], function(a ,b) {
  a.doSomething()
  // 此處略去 100行
  b.doSomething()
   ...

ADM和CMD比較

-相同之處
RequireJS 和 Sea.js 都是模塊加載器,倡導(dǎo)模塊化開發(fā)理念,核心價(jià)值是讓 JavaScript 的模塊化開發(fā)變得簡單自然。

-不同之處
兩者的主要區(qū)別如下:

  1. 定位有差異。RequireJS 想成為瀏覽器端的模塊加載器,同時(shí)也想成為 Rhino / Node 等環(huán)境的模塊加載器。Sea.js 則專注于 Web 瀏覽器端,同時(shí)通過 Node 擴(kuò)展的方式可以很方便跑在 Node 環(huán)境中。
    遵循的規(guī)范不同。RequireJS 遵循 AMD(異步模塊定義)規(guī)范,Sea.js 遵循 CMD (通用模塊定義)規(guī)范。規(guī)范的不同,導(dǎo)致了兩者 API 不同。Sea.js 更貼近 CommonJS Modules/1.1 和 Node Modules 規(guī)范。

  2. 推廣理念有差異。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數(shù)社區(qū)采納。Sea.js 不強(qiáng)推,采用自主封裝的方式來“海納百川”,目前已有較成熟的封裝策略。

  3. 對開發(fā)調(diào)試的支持有差異。Sea.js 非常關(guān)注代碼的開發(fā)調(diào)試,有 nocache、debug 等用于調(diào)試的插件。RequireJS 無這方面的明顯支持。

  4. 插件機(jī)制不同。RequireJS 采取的是在源碼中預(yù)留接口的形式,插件類型比較單一。Sea.js 采取的是通用事件機(jī)制,插件類型更豐富。

  5. 還有不少差異,涉及具體使用方式和源碼實(shí)現(xiàn),歡迎有興趣者研究并發(fā)表看法。

總之,如果說 RequireJS 是 Prototype 類庫的話,則 Sea.js 致力于成為 jQuery 類庫。

ES6 模塊化

ES6 模塊化采用靜態(tài)編譯,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量。CommonJS 和 AMD 模塊,都只能在運(yùn)行時(shí)確定這些東西。

對于 CommonJS 和 ES6 中的模塊化的兩者區(qū)別是:

前者支持動態(tài)導(dǎo)入,也就是 require(${path}/xx.js),后者目前不支持。

前者是同步導(dǎo)入,因?yàn)橛糜诜?wù)端,文件都在本地,同步導(dǎo)入即使卡住主線程影響也不大。而后者是異步導(dǎo)入,因?yàn)橛糜跒g覽器,需要下載文件,如果也采用同步導(dǎo)入會對渲染有很大影響。

前者在導(dǎo)出時(shí)都是值拷貝,就算導(dǎo)出的值變了,導(dǎo)入的值也不會改變,所以如果想更新值,必須重新導(dǎo)入一次。但是后者采用實(shí)時(shí)綁定的方式,導(dǎo)入導(dǎo)出的值都指向同一個內(nèi)存地址,所以導(dǎo)入值會跟隨導(dǎo)出值變化

最后編輯于
?著作權(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)容