模組化主要是用來抽離公共程式碼,隔離作用域,避免變數衝突等。將一個複雜的系統分解為多個模組以方便編碼。
會講述以下內容
- CommonJS
- AMD 及 核心原理實現
- CMD 及 核心原理實現
- UMD 及 原始碼解析
- ES6 Module
- webpack打包策略
CommonJS
同步載入
CommonJS API是以在瀏覽器環境之外構建 JS 生態系統為目標而產生的專案
如果沒有寫字尾名Node會嘗試為檔名新增.js、.json、.node後再搜尋。
.js件會以文字格式的JavaScript指令碼檔案解析,.json檔案會以JSON格式的文字檔案解析,.node檔案會以編譯後的二進位制檔案解析。
AMD
非同步載入(物件)
"Asynchronous Module Definition"(非同步模組定義),是由RequireJS提出的
AMD核心實現
function require (url, callback) {
// url可以換成List,然後遍歷;
var $script = document.createElement('script');
$script.src = url;
// 利用onload回撥,實現依賴載入
$script.onload = function (e) {
// 省略callback 檢測
callback();
}
document.body.appendChild($script);
}
複製程式碼
CMD
按需載入
由玉伯提出的(seajs),按需解析載入模組(代價挺大的),需要使用把模組變為字串解析一遍才知道依賴了那些模組
CMD核心實現
// 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 {
// 省略...
}
}
}
// 實現
function require(url) {
myAjax(url, function(res) {
// 此時 res 的對應JS的 String形式
// 解析 省略
// 執行
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
載入引用
- 編譯時載入(靜態執行)。
- 載入的是引用
- 不能處於程式碼塊中
- 為了實現編譯時載入
- 提案表示可以用
import()
使用時載入
- 提案表示可以用
- 為了實現編譯時載入
- 不能使用表示式和變數 等執行時載入的語法
- 同上
webpack打包策略
import會被編譯成 require/exports (CommonJS規範)
1. 直接引入
import xxx.js
或者import xxx.css
會像新增<script>
和<link>
標籤一樣注入到全域性中去
2. commonjs同步語法
webpack會將require('abc.js')
打包進引用它的檔案中。以物件的形式獲取。
3. commonjs非同步載入
webpack(require.ensure):webpack 2.x 版本中的程式碼分割。
在commonjs中有一個Modules/Async/A規範,裡面定義了require.ensure
語法。webpack實現了它,作用是可以在打包的時候進行程式碼分片,並非同步載入分片後的程式碼。
此時list.js會被打包成一個單獨的chunk檔案。像這樣:1.d6f343b727f5923508bf.js
例如:vue路由懶載入const Foo = () => import('./Foo.vue')
manifest
manifest檔案是最先載入的,manifest是在vendor的基礎上,再抽取出要經常變動的部分,通過manifest.js檔案來管理bundle檔案的執行和載入。(比如關於非同步載入js模組部分的內容)
webpack v4.6.0+ 新增了預取和預載入的支援
import(/* webpackPrefetch: true */ 'LoginModal');
會生成 <link rel="prefetch" href="login-modal-chunk.js"> 並追加到頁面頭部
複製程式碼