耐得住寂寞也是一種境界
js的模組化程序
現在前端技術日新月異,對於同一個問題痛點,各個時段有各自的解決方案,這就帶來了很大差異。今天我就打算梳理js模組化的歷史程序,講一講這些方案要做什麼,怎麼做。
js模組化程序的起因
現今的很多網頁其實可以看做是功能豐富的應用,它們擁有著複雜的JavaScript程式碼和一大堆依賴包。當一個專案開發的越來越複雜的時候,你會遇到一些問題:命名衝突(變數和函式命名可能相同),檔案依賴(引入外部的檔案數目、順序問題)等。
JavaScript發展的越來越快,超過了它產生時候的自我定位。這時候js模組化就出現了。
什麼是模組化
模組化開發是一種管理方式,是一種生產方式,一種解決問題的方案。他按照功能將一個軟體切分成許多部分單獨開發,然後再組裝起來,每一個部分即為模組。當使用模組化開發的時候可以避免剛剛的問題,並且讓開發的效率變高,以及方便後期的維護。
js模組化程序
一、早期:script標籤
這是最原始的 JavaScript 檔案載入方式,如果把每一個檔案看做是一個模組,那麼他們的介面通常是暴露在全域性作用域下,也就是定義在 window 物件中。
缺點:
1.汙染全域性作用域
2.只能按script標籤書寫順序載入
3.檔案依賴關係靠開發者主觀解決
二、發展一:CommonJS規範
允許模組通過require方法來同步載入(同步意味阻塞)所要依賴的其他模組,然後通過module.exports來匯出需要暴露的介面。
// module add.js module.exports = function add (a, b) { return a + b; } // main.js var {add} = require('./math'); console.log('1 + 2 = ' + add(1,2);
CommonJS 是以在瀏覽器環境之外構建JavaScript 生態系統為目標而產生的專案,比如在伺服器和桌面環境中。
三、發展二:AMD/CMD
(1)AMD
AMD 是 RequireJS 在推廣過程中對模組定義的規範化產出(非同步模組定義)。
AMD標準中定義了以下兩個API:
- require([module], callback);
- define(id, [depends], callback);
require介面用來載入一系列模組,define介面用來定義並暴露一個模組。
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好 a.add1() ... b.add2() ... })
優點:
1、適合在瀏覽器環境中非同步載入模組 2、可以並行載入多個模組
(2)CMD
CMD 是 SeaJS 在推廣過程中對模組定義的規範化產出。(在CommomJS和AMD基礎上提出)
define(function (requie, exports, module) {
//依賴可以就近書寫
var a = require('./a');
a.add1();
...
if (status) {
var b = requie('./b');
b.add2();
}
});
優點:
1、依賴就近,延遲執行 2、可以很容易在伺服器中執行
(3)AMD 和 CMD 的區別
AMD和CMD起來很相似,但是還是有一些細微的差別:
1、對於依賴的模組,AMD是提前執行,CMD是延遲執行。
2、AMD推崇依賴前置;CMD推崇依賴就近,只有在用到某個模組的時候再去require。
3、AMD 的 API 預設是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一
四、發展三:ES6模組化
EcmaScript6 標準增加了JavaScript語言層面的模組體系定義。
在 ES6 中,我們使用export關鍵字來匯出模組,使用import關鍵字引用模組。
// module math.jsx
export default class Math extends React.Component{}
// main.js
import Math from "./Math";
目前很少JS引擎能直接支援 ES6 標準,因此 Babel 的做法實際上是將不被支援的import翻譯成目前已被支援的require。