前端模組化AMD、CMD、CommonJS&ES6

littleStar發表於2019-04-28
  • 模組化的必要性:
    為了提高程式碼的開發效率,方便程式碼的維護,重構。

  • 模組化與元件化的區別:
    模組可以理解為分解的頁面邏輯,比如一個網站的登入,使用者管理等; 元件則是一個具體的功能。 具體來說一個下拉框是一個元件,一個登入功能一個模組。

  • 目前常見的模組化規範(排名不分先後):

    1. AMD
    2. CMD
    3. CommonJS
    4. ES6
1. AMD

AMD與CMD類似,不同的是AMD推崇依賴前置,--requireJS 推廣過程中出現的規範。

/** main.js中引入1.js及2.js **/
// 執行基本操作
define(["1.js","2.js"],function($,_){
  // some code here
});
/** 如果1.js中又引入了3.js,那就會先廣度優先,然後深度遍歷。   
請求1.js和2.js然後在1.js中進行3.js的請求,3.js返回結果後檢視2.js是否已經返回,   
如果已經返回則合併結果後返回給main.js
**/
複製程式碼
2. CMD

CMD推崇就近依賴。 --sea.js推廣過程中出現的規範。
但是因為在AMD&CMD都是在瀏覽器端使用,採用的是非同步載入,其實CMD還是需要在一開始就請求需要的,只是寫法上更方便了。(採用的是正則匹配來獲得js檔名,所以註釋掉的仍然會請求,並且只可以書寫字串,不可以使用表示式)

/** AMD寫法 **/
define(["1", "2"], function(1, 2) { 
     // 依賴前置
  function foo(){
    lib.log('hello world!');
  }

  return {
    foo: foo
  };
});

/** CMD寫法 **/
define(function(require, exports, module) {
    var test = require('./1'); //就近依賴
    test.sayHi();
});

複製程式碼
3. CommonJS

大前端使用的Node即時CommonJS的例項。
與AMD&CMD的不同之處在於CommonJS規範載入模組是同步的,也就是說,只有載入完成,才能執行後面的操作。

require引數規則:
3.1. 如果引數字串以“/”開頭,則表示載入的是一個位於絕對路徑的模組檔案。   
比如,require('/home/marco/foo.js')將載入/home/marco/foo.js。   
3.2. 如果引數字串以“./”開頭,則表示載入的是一個位於相對路徑(跟當前執行指令碼的位置相比)的模組檔案。   
比如,require('./circle')將載入當前指令碼同一目錄的circle.js。   
3.3. 如果引數字串不以“./“或”/“開頭,則表示載入的是一個預設提供的核心模組(位於Node的系統安裝目錄中),   
或者一個位於各級node_modules目錄的已安裝模組(全域性安裝或區域性安裝)。   
3.4. 如果引數字串不以“./“或”/“開頭,而且是一個路徑,比如require('example-module/path/to/file'),   
則將先找到example-module的位置,然後再以它為引數,找到後續路徑。   
3.5. 如果指定的模組檔案沒有發現,Node會嘗試為檔名新增.js、.json、.node後,再去搜尋。    
.js件會以文字格式的JavaScript指令碼檔案解析,.json檔案會以JSON格式的文字檔案解析,   
.node檔案會以編譯後的二進位制檔案解析。   
3.6. 如果想得到require命令載入的確切檔名,使用require.resolve()方法。
複製程式碼
const webpack = require('webpack');//引入
const sayHi = function (){
    console.log('haha');
}
module.exports = {
    sayHi:sayHi
}//匯出
複製程式碼
4. ES6

相對於以上的AMD&CMD是用於瀏覽器端,CommonJS用於伺服器端。ES6的模組化非常可喜可賀的是瀏覽器和伺服器通用的模組解決方案。

那它是怎麼做到的呢?
區別與以上三者需要在 進行時載入,ES6儘量的靜態化,使得編譯時就能確定模組的依賴關係,以及輸入和輸出的變數。

使用:
ES6使用import進行引入,export default(比export更友好)進行匯出。

import { lastName as surname } from './profile.js';
function foo() {
  console.log('foo');
}

export default foo;
複製程式碼

參考文章:

  1. 《JavaScript 標準參考教程(alpha)》,by 阮一峰
  2. 《ECMAScript 6 入門》,by 阮一峰

相關文章