模塊化主要是用來抽離公共代碼,隔離作用域,避免變量沖突等。將一個復(fù)雜的系統(tǒng)分解為多個模塊以方便編碼。
會講述以下內(nèi)容
- CommonJS
- AMD 及 核心原理實現(xiàn)
- CMD 及 核心原理實現(xiàn)
- UMD 及 源碼解析
- ES6 Module
- webpack打包策略
CommonJS
同步加載
CommonJS API是以在瀏覽器環(huán)境之外構(gòu)建 JS 生態(tài)系統(tǒng)為目標(biāo)而產(chǎn)生的項目
如果沒有寫后綴名Node會嘗試為文件名添加.js、.json、.node后再搜索。
.js件會以文本格式的JavaScript腳本文件解析,.json文件會以JSON格式的文本文件解析,.node文件會以編譯后的二進(jìn)制文件解析。
AMD
異步加載(對象)
"Asynchronous Module Definition"(異步模塊定義),是由RequireJS提出的
AMD核心實現(xiàn)
function require (url, callback) {
// url可以換成List,然后遍歷;
var $script = document.createElement('script');
$script.src = url;
// 利用onload回調(diào),實現(xiàn)依賴加載
$script.onload = function (e) {
// 省略callback 檢測
callback();
}
document.body.appendChild($script);
}
CMD
按需加載
由玉伯提出的(seajs),按需解析加載模塊(代價挺大的),需要使用把模塊變?yōu)樽址馕鲆槐椴胖酪蕾嚵四切┠K
CMD核心實現(xiàn)
// ajax,怕忘了原生ajax怎么寫。順手寫一個
function myAjax (url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.send();
xhr.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
return callback(request.responseText);
} else {
// 省略...
}
} else {
// 省略...
}
}
}
// 實現(xiàn)
function require(url) {
myAjax(url, function(res) {
// 此時 res 的對應(yīng)JS的 String形式
// 解析 省略
// 執(zhí)行
eval(res);
});
}
UMD
兼容AMD,CommonJS 模塊化語法。
UMD源碼解析
(function (root, factory) {
// 判斷是否支持AMD(define是否存在)
if (typeof define === 'function' && define.amd) {
define(['b'], factory);
// 判斷是否支持NodeJS模塊格式(exports是否存在)
} else if (typeof module === 'object' && module.exports) {
module.exports = factory(require('b'));
// 前兩個都不存在,則將模塊公開到全局(window或global)
} else {
root.returnExports = factory(root.b);
}
} (this, function (b) {
// ...
}));
import
加載引用
- 編譯時加載(靜態(tài)執(zhí)行)。
- 加載的是引用
- 不能處于代碼塊中
- 為了實現(xiàn)編譯時加載
- 提案表示可以用
import()使用時加載
- 提案表示可以用
- 為了實現(xiàn)編譯時加載
- 不能使用表達(dá)式和變量 等運行時加載的語法
- 同上
webpack打包策略
import會被編譯成 require/exports (CommonJS規(guī)范)
1. 直接引入
import xxx.js或者import xxx.css會像添加<script>和<link>標(biāo)簽一樣注入到全局中去
2. commonjs同步語法
webpack會將require('abc.js')打包進(jìn)引用它的文件中。以對象的形式獲取。
3. commonjs異步加載
webpack(require.ensure):webpack 2.x 版本中的代碼分割。
在commonjs中有一個Modules/Async/A規(guī)范,里面定義了require.ensure語法。webpack實現(xiàn)了它,作用是可以在打包的時候進(jìn)行代碼分片,并異步加載分片后的代碼。
此時list.js會被打包成一個單獨的chunk文件。像這樣:1.d6f343b727f5923508bf.js
例如:vue路由懶加載const Foo = () => import('./Foo.vue')
manifest
manifest文件是最先加載的,manifest是在vendor的基礎(chǔ)上,再抽取出要經(jīng)常變動的部分,通過manifest.js文件來管理bundle文件的運行和加載。(比如關(guān)于異步加載js模塊部分的內(nèi)容)
webpack v4.6.0+ 添加了預(yù)取和預(yù)加載的支持
import(/* webpackPrefetch: true */ 'LoginModal');
會生成 <link rel="prefetch" href="login-modal-chunk.js"> 并追加到頁面頭部