前端子產品化
- 将代碼以功能區分,分成各個子產品。
子產品化演進過程
- 最早期:以檔案形式劃分
-
- 将js代碼分成各個子產品檔案,以script src引入
-
- 這種模式會帶來很多問題:
-
-
- -污染全局變量
-
-
-
- 命名沖突
-
-
-
- 無法管理子產品依賴關系
-
-
-
- 完全依靠約定
-
- 第二階段:命名空間方式
-
- 将方法、變量用JavaScript Object包裹
- 第三階段: 使用立即執行函數包裹
-
- 實作了私有成員的概念
-
- 用立即執行函數的參數來表名依賴關系
- 以上的形式 非常依賴手動加載子產品,以及加載順序
AMD
實作
- 浏覽器端 – require.js
說明
- 依賴必須提前聲明好
- 子產品加載異步,指定回調函數
基本文法
引入
//通過數組引入依賴,回調函數通過形參傳入依賴
define(['Module1', ‘Module2’], function (Module1, Module2) {
function foo () {
/// someing
Module1.test();
}
return {foo: foo}
});
優點
适合在浏覽器環境中異步加載子產品。可以并行加載多個子產品
缺點
提高開發成本,不能按需加載,必須提前加載所有的依賴,使用相對複雜,子產品js檔案請求頻繁
CMD
實作
- 浏覽器端 – sea.js
說明
- 對于依賴的子產品AMD是提前執行,CMD是延遲執行
- AMD推崇依賴前置 CMD推崇依賴就近
- 整合了commonjs和amd的特點
- 子產品的加載是異步的,子產品使用時才會加載執行
基本文法
引入
define(function (require, exports, module) {
//依賴可以就近書寫
var a = require('./a');
a.test();
...
//軟依賴
if (status) {
var b = requie('./b');
b.test();
}
});
define(function(require,exports, module) {
exports.xxx = value
module.exports = value
})
define(function(require,exports, module) {
var module2 = require('./module2')
require.async('./module3', function(module3) {
......
})
module.exports = value
})
優點
可以按需加載,依賴就近
缺點
依賴SPM打包,子產品的加載邏輯偏重
COMMON.JS
實作
- 服務端 – node
- 浏覽器 – webpack、browserfy
說明
- 子產品加載同步,資源加載完再執行
- 每個檔案都可以是一個子產品
- 服務端 子產品加載時運作時同步加載
- 浏覽器 子產品加載是提前編譯打包處理
- 對于基本資料類型,屬于複制。會被子產品緩存
- 對于複雜資料類型 屬于淺拷貝。由于兩個子產品引用 的對象指向同一個記憶體空間,值修改會影響另一個子產品
- 當使用require指令加載某個子產品時,就會運作整個子產品的代碼
- 當使用require加載同一個子產品時,不會再執行該子產品,就傳回第一次執行的結果
- 循環加載時,屬于加載時執行
基本文法
// 引入子產品
// 第三方
var fs = require('fs')
//自定義子產品
require('./xxx,jpg')
//讀入并執行一個js檔案,然後傳回該子產品的exports對象,如果沒有就會報錯
//暴露子產品
module.exports = value
exports.xxx = value
//module變量代表目前子產品。這個變量是一個對象,它的exports屬性是對外的接口
ES6 MODULE
實作
- 服務端和浏覽器通用
- 浏覽器端 — 目前需要Babel将es6轉成es5、Browserfy編譯
說明
- 依賴需要提前聲明 import在頂層
- es6子產品中的值屬于 動态隻讀引用
- 對于隻讀來說,不允許修改引入變量的值,當子產品遇到import指令時就會生成一個隻讀引用,等到腳本真正執行時,再根據隻讀引用,到被加載的那個子產品裡面去取值
- 對于動态來說,原始值發生變化,import加載的值也會發生變化,不論是什麼類型
- 循環加載時,ES6子產品是動态引用,隻要兩個子產品之間存在某個引用,代碼就能執行
基本文法
//引入
import
import xxx from 'xxx.js'
import {xxx} from 'xxx.js'
//暴露
export
export default module
export module
和commonjs的差別
es6輸出的是隻讀引用、commonjs輸出的是值的淺拷貝
因為commonjs加載的是一個對象,該對象隻有在腳本運作完才會生成
es6不是對象,它的對外接口隻是一種靜态定義,在代碼靜态解析階段就會生成