前端模組化規範
阿新 • • 發佈:2022-02-07
前端為什麼需要模組化?
隨著前端能承擔更多的開發責任,各種問題開始凸顯,全域性變數衝突、依賴關係難以管理、資料安全問題等等。
什麼是模組?
- 將一個複雜的程式依據一定的規則封裝成幾個塊,並進行組合在一起。
- 塊的內部資料與實現是私有的,只是向外部暴露一些介面(方法)與外部其它模組通訊。
模組化的好處?
- 避免命名衝突(減少名稱空間汙染)
- 更多的分離,按需載入
- 更高複用性
- 高可維護性
那麼模組化規範有哪些呢?
模組化規範
CommonJS
CommonJS
是伺服器端模組的規範,Node.js
採用了這個規範。每個檔案就是一個模組,有自己的作用域。在一個檔案裡面定義的變數、函式、類,都是私有的,對其他檔案不可見。在伺服器端,模組的載入是執行時同步載入的;在瀏覽器端,模組需要提前編譯打包處理。
(1)、基本語法
// 定義模組math.js
const value = 1
const add = function(){
value++
}
module.exports = {
value,
add
}
// 引入模組math.js
const math = require('./math')
math.add()
// 會發現value的值還是1
console.log(math.value)
注意匯出的時候還可以使用exports.xxx = value
。
(2)、特點
- 同步載入,由於
CommonJS
是用於伺服器端的,伺服器端的檔案都在本地,所以沒什麼影響,但是用於瀏覽器就不行了,檔案都是要下載的,採用同步載入的方式就會導致阻塞。 - 輸出的是值的拷貝,所以值改變時,不影響之前匯出的值。
- 執行時載入,所以無法做到提前分析依賴以及
Tree-Shaking
。 - 所有程式碼都執行在模組作用域,不會汙染全域性作用域。
- 模組可以多次載入,但是隻會在第一次載入時執行一次,然後執行結果就被快取了,以後再載入,就直接讀取快取結果,要想讓模組再次執行,必須清除快取。
- 模組載入的順序,按照其在程式碼中出現的順序。
AMD
主要用於客戶端,非同步載入。AMD
和CommonJS
的主要區別在於它是否支援非同步模組載入。
// 定義匯出模組 // 不依賴其它模組的模組定義 define(function(){ return 模組 }) // 依賴其它模組的模組定義 // 第一個引數[module],是一個數組,裡面的成員就是要載入的模組;第二個引數callback,則是載入成功之後的回撥函式。 define(['module1', 'module2'], function(m1, m2){ return 模組 })
// 引入模組
require(['module1', 'module2'], function(m1, m2){
return 模組
})
UMD
它就像是一個工廠,為了同時支援CommonJS
和AMD
的規範,判斷誰的規範支援就使用誰的規範,他的外層是一個iife
。並且支援直接在前端用<script src="lib.umd.js"></script>
的方式載入。
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {}
}));
ESM
ES6
模組的設計思想,是儘量的靜態化,使得編譯時就能確定模組的依賴關係,以及輸入和輸出的變數。
瀏覽器直接通過<script type="module">
即可使用該寫法。NodeJS
可以通過mjs
字尾或者在package.json
新增"type": "module"
來使用。
(1)、基本語法
// 定義模組 math.js
var basicNum = 0;
var add = function (a, b) {
return a + b;
};
export { basicNum, add };
// 引用模組
import { basicNum, add } from './math';
function test(ele) {
ele.textContent = add(99 + basicNum);
}
(2)、特點
- 完全替代
CJS
和AMD
,淘汰了UMD
,名稱空間等規範。 - 靜態化,編譯時載入,使得頁面載入速度快。
ES6
模組的執行機制與CommonJS
不一樣,它遇到模組載入命令import
時,不會去執行模組,而是隻生成一個動態的只讀引用。等到真的需要用到時,再到模組裡面去取值。import
命令具有提升效果,因為是編譯時載入,所以會比其他程式碼都先執行。ES6
模組輸出的是值的引用,值改變時,原本輸出的值也會變化。
參考文章
1、前端模組化詳解(完整版)
2、前端模組化一——規範詳述
3、前端模組化iife、CJS、AMD、UMD、ESM的區別
4、打包umd_cjs, umd, esm or iife?