js 模塊化的規范


       The Module Pattern,模塊模式,也譯為模組模式,是一種通用的對代碼進行模塊化組織與定義的方式。這里所說的模塊(Modules),是指實現某特定功能的一組方法和代碼。許多現代語言都定義了代碼的模塊化組織方式,比如 Golang 和 Java,它們都使用 package 與 import 來管理與使用模塊,而目前版本的 JavaScript 並未提供一種原生的、語言級別的模塊化組織模式,而是將模塊化的方法交由開發者來實現。因此,出現了很多種 JavaScript 模塊化的實現方式,比如,CommonJS Modules、AMD 等。 

 

1、CommonJS 是一個有志於構建 JavaScript 生態圈的組織。整個社區致力於提高 JavaScript 程序的可移植性和可交換性,無論是在服務端還是瀏覽器端。

     a group with a goal of building up the JavaScript ecosystem for web servers, desktop and command line apps and in the browser.

    一個有目標的構建JavaScript生態系統Web服務器組,在瀏覽器和命令行應用程序和桌面。(他自己wiki上這么說的)

           這個組織呢制定了一些規范 (可以去他們網站看看 http://www.commonjs.org/)包括CommonJS Modules/1.0 規范,我們平時所說的commonjs規范,說的就是這個了。

          “The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, Ruby and Java. ”--(出自 http://www.commonjs.org/

    所以說Commonjs是一個更偏向於服務器端的規范。Node.js采用了這個規范。 根據CommonJS規范,一個單獨的文件就是一個模塊。加載模塊使用require方法,該方法讀 取一個文件並執行,最后返回文件內部的exports對象。

        他又說了,可以用在下面這些場景  ,所以他更明顯的偏向服務器端。當然你也可以把它用在瀏覽器里邊(他們自己說可以)。

  • Server-side JavaScript applications
  • Command line tools
  • Desktop GUI-based applications
  • Hybrid applications (Titanium, Adobe AIR)

 

 

2、AMD規范

   Commonjs解決了模塊化的問題,並且可以用在瀏覽器中,但是Commonjs是同步加載模塊,當要用到該模塊了,現加載現用,這種同步機制到了瀏覽器里邊就有問題了,加載速度啊啥的(覽器同步加載模塊會導致性能、可用性、調試和跨域訪問等問題)。

    鑒於瀏覽器的特殊情況,又出現了一個規范,這個規范呢可以實現異步加載依賴模塊,並且會提前加載那就是AMD規范。AMD可以作為CommonJS模塊一個中轉的版本只要CommonJS沒有被用來同步的require調用。使用同步require調用的CommonJS代碼可以被轉換為使用回調風格的AMD模塊加載器(https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88)  (它說的)。

    

    下面是一個使用了簡單CommonJS轉換的模塊定義(它是amd規范的一種用法):

     define(function (require, exports, module) {   var a = require('a'),   b = require('b');   exports.action = function () {};   });

    所以說AMD和Commonjs是兼容的,只要稍稍調換一下調用方法就實現了同步加載(我很懷疑amd也是在commonjs基礎上加了個殼,然后並沒有找到其他的神馬說明和支持的文字,找到了一定加到這)。

    看一下AMD規范你會發現,AMD基本都是提前說明依賴模塊,然后預加載這些模塊,實際上這就要求你提前想好這些依賴,提前寫好,不然寫代碼過程中要回到開頭繼續添加依賴。

 

3、CMD

    不知道是不是針對這個問題,淘寶的玉伯大牛搞了個seajs出來,並聲稱這個規范是遵循CMD規范的,然后給出了這個規范的一個連接(打開會發現draft字樣)。關於這個規范呢玉伯在知乎是這么說的

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

      CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
      類似的還有 CommonJS Modules/2.0 規范,是 BravoJS 在推廣過程中對模塊定義的規范化產出。
      還有不少⋯⋯

      “

     所以這個規范實際上是為了Seajs的推廣然后搞出來的。那么看看SeaJS是怎么回事兒吧,基本就是知道這個規范了。

    同樣Seajs也是預加載依賴js跟AMD的規范在預加載這一點上是相同的,明顯不同的地方是調用,和聲明依賴的地方。AMD和CMD都是用difine和require,但是CMD標准傾向於在使用過程中提出依賴,就是不管代碼寫到哪突然發現需要依賴另一個模塊,那就在當前代碼用require引入就可以了,規范會幫你搞定預加載,你隨便寫就可以了。但是AMD標准讓你必須提前在頭部依賴參數部分寫好(沒有寫好? 倒回去寫好咯)。這就是最明顯的區別。

 

簡單的區別


AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。  
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。

 

 

區別:

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

2. CMD 推崇依賴就近,AMD 推崇依賴前置。看代碼:

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

// AMD 默認推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
a.doSomething()
// 此處略去 100 行
b.doSomething()
...
}) 

雖然 AMD 也支持 CMD 的寫法,同時還支持將 require 作為依賴項傳遞,但 RequireJS 的作者默認是最喜歡上面的寫法,也是官方文檔里默認的模塊定義寫法。


3. AMD 的 API 默認是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啟動。CMD 里,每個 API 都簡單純粹

 CommonJS 與AMD,CMD的區別

CommonJS服務器端范疇,AMD,CMD客戶瀏覽器端范疇

 

當我們寫一個文件需要兼容不同的加載規范的時候怎么辦呢,看看下面的代碼。

(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(){}; // 私有方法,因為它沒被返回 (見下面)
 
    function b(){}; // 公共方法,因為被返回了
 
    function c(){}; // 公共方法,因為被返回了
 
      
 
    // 暴露公共方法
 
    return {
 
        b: b,
 
        c: c
 
    }
 
}));   

 

參考文檔

https://my.oschina.net/chenzhiqiang/blog/129783

 

擴展閱讀:
 
AMD規范文檔  https://github.com/amdjs/amdjs-api/wiki/AMD
amdjs 的 require 接口文檔  https://github.com/amdjs/amdjs-api/wiki/require
amdjs 的接口文檔  https://github.com/amdjs/amdjs-api/wiki
RequireJS官網接口文檔   http://www.requirejs.org/docs/api.html 
 
前端模塊化開發的價值  https://github.com/seajs/seajs/issues/547
前端模塊化開發那點歷史  https://github.com/seajs/seajs/issues/588
從 CommonJS 到 Sea.js  https://github.com/seajs/seajs/issues/269    

RequireJS和AMD規范  http://javascript.ruanyifeng.com/tool/requirejs.html 

知乎  AMD 和 CMD 的區別有哪些? http://www.zhihu.com/question/20351507 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM