1. 程式人生 > 其它 >前端模組化規範

前端模組化規範

前端為什麼需要模組化?

隨著前端能承擔更多的開發責任,各種問題開始凸顯,全域性變數衝突、依賴關係難以管理、資料安全問題等等。

什麼是模組?

  • 將一個複雜的程式依據一定的規則封裝成幾個塊,並進行組合在一起。
  • 塊的內部資料與實現是私有的,只是向外部暴露一些介面(方法)與外部其它模組通訊。

模組化的好處?

  • 避免命名衝突(減少名稱空間汙染)
  • 更多的分離,按需載入
  • 更高複用性
  • 高可維護性

那麼模組化規範有哪些呢?

模組化規範

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

主要用於客戶端,非同步載入。AMDCommonJS的主要區別在於它是否支援非同步模組載入。

// 定義匯出模組
// 不依賴其它模組的模組定義
define(function(){
   return 模組
})
// 依賴其它模組的模組定義
// 第一個引數[module],是一個數組,裡面的成員就是要載入的模組;第二個引數callback,則是載入成功之後的回撥函式。
define(['module1', 'module2'], function(m1, m2){
   return 模組
})
// 引入模組
require(['module1', 'module2'], function(m1, m2){
    return 模組
})

UMD

它就像是一個工廠,為了同時支援CommonJSAMD的規範,判斷誰的規範支援就使用誰的規範,他的外層是一個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)、特點

  • 完全替代CJSAMD,淘汰了UMD,名稱空間等規範。
  • 靜態化,編譯時載入,使得頁面載入速度快。
  • ES6模組的執行機制與CommonJS不一樣,它遇到模組載入命令import時,不會去執行模組,而是隻生成一個動態的只讀引用。等到真的需要用到時,再到模組裡面去取值。
  • import命令具有提升效果,因為是編譯時載入,所以會比其他程式碼都先執行。
  • ES6模組輸出的是值的引用,值改變時,原本輸出的值也會變化。

參考文章

1、前端模組化詳解(完整版)
2、前端模組化一——規範詳述
3、前端模組化iife、CJS、AMD、UMD、ESM的區別
4、打包umd_cjs, umd, esm or iife?