天天看點

前端子產品化(AMD,CMD,CommonJs,ES6)前端子產品化

前端子產品化

  • 将代碼以功能區分,分成各個子產品。

子產品化演進過程

  • 最早期:以檔案形式劃分
    • 将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不是對象,它的對外接口隻是一種靜态定義,在代碼靜态解析階段就會生成

繼續閱讀