詳解AMD、CommonJS和UMD模組化規範
阿新 • • 發佈:2019-02-07
開發的時候,我們經常會把某些功能封裝成可複用的模組。模組封裝了功能,並且對外暴露一個API。隨著Node.js的誕生和發展,JavaScript可以在服務端執行,同時客戶端應用也越來越流行,JavaScript界產生了對優秀和健壯模組系統的需求。在JavaScript中定義模組的規範也隨之產生。
這裡,將詳細介紹最常見的兩個定義模組的方法AMD和CommonJS,以及它們的結合UMD.
一、CommonJS
CommonJS模組可以說是當前最流行的模組定義規範。相比於AMD,它的工作效率更高、語法更簡單。一開始,CommonJS模組是JavaScript伺服器模組的規範。
基本原理
實現編譯程式碼,建立一個比原先更大的程式碼包,其中包含了所有應用執行所需的程式碼。
語法
const $ = require('jquery'); //將依賴載入到當前檔案
exports.init = function(){
...
};
特點
- 沒有回撥函式
- 同步載入,每個require語句會短暫阻塞程式碼的執行,知道模組載入完畢。不過這個載入不是通過網路載入,而是從記憶體或者檔案系統中載入,所以這個過程很快。
- 程式碼簡單易懂
- CommonJS模組不適合瀏覽器,因為瀏覽器的載入機制不支援同步。需要用打包工具把所有CommonJS模組打包成一個js檔案。
二、AMD——為瀏覽器設計的模組定義規範
AMD:Asynchronous Module Definition(非同步模組規範),最老的方式之一,專為瀏覽器而設計。
基本原理
用非同步載入技術來定義模組和依賴。提供define方法和require方法來定義和載入模組。
語法
define方法:
define(
'模組id',
['依賴陣列'],
function([依賴陣列]){ //工廠函式
...
}
);
工廠函式內部包含了模組程式碼,工廠函式最後返回的結果,就是要暴露給其他模組的功能。
特點
- 用AMD定義的模組至少需要一個工廠函式來暴露API給其他模組使用。
- 依賴陣列中的依賴會被非同步載入。
- 模組的載入通過客戶端(瀏覽器)向伺服器傳送HTTP請求來完成的,這個傳輸過程需要大量時間。
- 可以定義具名模組,也可以定義匿名模組。具名模組通過開發者定義的名字載入,匿名模組隱式的以檔名載入。
require方法:
require(['jquery'],
function($){ //回撥函式
...
}
);
require方法與define方法相對應,用來顯示的載入模組。
特點
- 可以在程式碼的任何地方使用require載入另一個模組。
- require呼叫會發送一個請求來下載模組。
- 非同步載入,只有在回撥函式裡才能獲取新拿到的API。
AMD模組載入流程示意圖
UMD——通用模組規範
UMD:Universal Module Definition(通用模組規範)是由社群想出來的一種整合了CommonJS和AMD兩個模組定義規範的方法。
基本原理
用一個工廠函式來統一不同的模組定義規範。
原則
- 所有定義模組的方法需要單獨傳入依賴
- 所有定義模組的方法都需要返回一個物件,供其他模組使用
例如,利用UMD定義一個toggler模組:
(function (global, factory) {
if (typeof exports === 'object' && typeof module !== undefined) { //檢查CommonJS是否可用
module.exports = factory(require('jquery'));
} else if (typeof define === 'function' && define.amd) { //檢查AMD是否可用
define('toggler', ['jquery', factory])
} else { //兩種都不能用,把模組新增到JavaScript的全域性名稱空間中。
global.toggler = factory(global, factory);
}
})(this, function ($) {
function init() {
}
return {
init: init
}
});