JS模塊化

模塊化規(guī)范:CommonJS,AMD,CMD,UMD,ES6 Module

CommonJS

CommonJS是服務(wù)器端模塊的規(guī)范,Node.js采用了這個(gè)規(guī)范。是一種同步的方式。
根據(jù)CommonJS規(guī)范,一個(gè)單獨(dú)的文件就是一個(gè)模塊,使用exports/require方法。

//導(dǎo)出 module.exports
module.exports = { age: 1, a: 'hello', foo:function(){} }

//nodeJS中同步加載
var math = require('math');
math.add(2,3); 

服務(wù)器端的編程,需要加載的模塊文件一般都已經(jīng)存在本地硬盤(pán),加載起來(lái)比較快,所以CommonJS規(guī)范比較適用。但是在瀏覽器中如果用同步加載的方式會(huì)導(dǎo)致頁(yè)面卡頓,影響用戶(hù)體驗(yàn),所以就有了AMD。

AMD與RequireJS

AMD是"Asynchronous Module Definition"的縮寫(xiě),意思就是"異步模塊定義"。它采用異步方式加載模塊,模塊的加載不影響它后面語(yǔ)句的運(yùn)行。
所有依賴(lài)這個(gè)模塊的語(yǔ)句,都定義在一個(gè)回調(diào)函數(shù)中,等到加載完成之后,這個(gè)回調(diào)函數(shù)才會(huì)運(yùn)行

//模塊定義 define(id?, dependencies?, factory)
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
    exports.verb = function(){
        return beta.verb();
    }
});
//模塊加載 require([module], callback)
require(['math'], function(math) {
 math.add(2, 3);
});

RequireJS

RequireJS 是一個(gè)前端的模塊化管理的工具庫(kù),遵循AMD規(guī)范。

RequireJS 的基本思想為:通過(guò)一個(gè)函數(shù)來(lái)將所有所需要的或者說(shuō)所依賴(lài)的模塊實(shí)現(xiàn)裝載進(jìn)來(lái),然后返回一個(gè)新的函數(shù)(模塊),我們所有的關(guān)于新模塊的業(yè)務(wù)代碼都在這個(gè)函數(shù)內(nèi)部操作,其內(nèi)部也可無(wú)限制的使用已經(jīng)加載進(jìn)來(lái)的以來(lái)的模塊。

define定義模塊

//獨(dú)立模塊,不依賴(lài)其他模塊
define(function() {
    return {
        method1: function(){},
        method2: function(){}
    }
});
//非獨(dú)立模塊 define([modules], callback);
define([ 'module1', 'module2' ], function(m1, m2) {
    ...
});

require方法調(diào)用模塊

//require([modules], callback);
require(['foo', 'bar'], function(foo, bar) {
    foo.func();
    bar.func();
} );

CMD和SeaJS

AMD是"Common Module Definition" ,AMD是依賴(lài)前置(預(yù)加載),而CMD是依賴(lài)就近,想什么時(shí)候 require就什么時(shí)候加載,實(shí)現(xiàn)了懶加載(延遲執(zhí)行 )
CMD沒(méi)有全局 require, 每個(gè)API都簡(jiǎn)單純粹。

// CMD
define(function(require, exports, module) {  
    var a = require('./a')  
    a.doSomething();  
    ...
    var b = require('./b')   // 依賴(lài)可以就近書(shū)寫(xiě)  
    b.doSomething();
})

雖然RequireJS也支持SeaJS的寫(xiě)法,但是依賴(lài)的模塊任然是預(yù)先加載的

UMD

UMD(Universal Module Definition)是AMD+CommonJS+全局變量的結(jié)合

UMD先判斷是否支持Node.js的模塊(exports)是否存在,存在則使用Node.js模塊模式。
再判斷是否支持AMD(define是否存在),存在則使用AMD方式加載模塊。

(function (window, factory) {
    if (typeof exports === 'object')
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else {
        window.eventUtil = factory();
    }
})(this, function () {
    //module ...
});

有了 UMD 后我們的代碼和同時(shí)運(yùn)行在 Node 和 瀏覽器上,所以現(xiàn)在前端大多數(shù)的庫(kù)最后打包都使用的是 UMD 規(guī)范

ES6 Module

ES6后直接使用export/import就可以進(jìn)行模塊管理,不再需要AMD, CommonJS

export * from 'module'; //重定向?qū)С?不包括 module內(nèi)的default
export { name1, name2, ..., nameN } from 'module'; // 重定向命名導(dǎo)出
export { import1 as name1, import2 as name2, ..., nameN } from 'module'; // 重定向重命名導(dǎo)出

export { name1, name2, …, nameN }; // 與之前聲明的變量名綁定 命名導(dǎo)出
export { variable1 as name1, variable2 as name2, …, nameN }; // 重命名導(dǎo)出

export let name1 = 'name1'; // 聲明命名導(dǎo)出 或者 var, const,function, function*, class

export default expression; // 默認(rèn)導(dǎo)出
export default function () { ... } // 或者 function*, class
export default function name1() { ... } // 或者 function*, class
import { a, b, c } from 'module';  //命名導(dǎo)出
import { a as newA, b, c as newC } from 'module'; 

import 'module'; // 副作用,只是運(yùn)行module,不為了導(dǎo)出內(nèi)容,多次調(diào)用次語(yǔ)句只能執(zhí)行一次

var promise = import('module'); //動(dòng)態(tài)導(dǎo)入(異步導(dǎo)入)

注意項(xiàng)

1.語(yǔ)法是靜態(tài)的,import 會(huì)自動(dòng)提升到代碼的頂層
2.使用 import 導(dǎo)入的變量是只讀的,無(wú)法被賦值,而且是引用傳遞

與CommonJs的區(qū)別

1.CommonJs導(dǎo)出的是變量的一份拷貝,ES6 Module導(dǎo)出的是變量的綁定(引用)
2.CommonJs是單個(gè)值導(dǎo)出,ES6 Module可以導(dǎo)出多個(gè)
3.CommonJs是動(dòng)態(tài)語(yǔ)法可以寫(xiě)在判斷里,ES6 Module靜態(tài)語(yǔ)法只能寫(xiě)在頂層
4.CommonJs的 this 是當(dāng)前模塊,ES6 Module的 this 是 undefined

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

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