小記JS模塊化

有很長一段時間,我對JS模塊化的概念就是處於模糊的狀態。感覺自己的智商真的有點低。後來,突然發現模塊化其實就是C++中的include功能,說白了有點像類的封裝。茅塞頓開!!!

本文就稍微整理下JS的模塊化。

模塊化的背景

當項目變得複雜,可能會出現的問題:

  • 命名衝突
  • 按需載入
  • 依賴管理問題

於是就有了模塊的必要性。除了解決以上兩個問題之外,模塊化還有的好處是:

  • 可維護性
  • 代碼復用

我們來看看目前有哪些解決方案。總的來說,出現了命名空間,模塊模式,沙盒,依賴注入,CommonJS,AMD,CMD,UMD,ES6等解決方案。

命名空間(2002)

用對象的方式來模擬命名空間:

netease.add = function(){};siji.add = function(){};

此方法比較簡陋,多人需要約定協調。也僅僅在一定程度上解決了變數衝突的問題。

依賴注入(2004)

寫過Angular的人對這個詞一定不陌生,自從我有了模塊化的概念之後,我對依賴注入的理解就是模塊化的一種方式。但確切來說,是引入一個實例化對象。

模塊模式(?)

用立即執行函數的方式:

(function($){ var a = 1; // 私有變數 function b(){ //私有方法 // ... } return { //暴露給外部的介面 b: b }})(jQuery)

但仍沒有解決依賴關係,仍然要非常注意腳本的載入順序。比如上述例子,jQuery必須先載入,不然就會出錯。

沙盒(2009)

YUI3的沙盒機制:

YUI().use(node, function(Y){ // Your code goes here. })

仍然沒有解決依賴管理的問題。

CommonJS(2009)

用於服務端的模塊處理庫,每個文件都是一個模塊,Node遵循的就是CommonJS。導入模塊的方式:

//a.jsfunction add(x){ return x+1;}module.exports = add;//b.jsvar a = require(a.j); return a.add(4);

載入文件是同步載入的,在伺服器環境是可行的。但不能應用於瀏覽器。所以就出來了AMD,CMD的解決方案。

AMD(2009)

AMD是Asynchromous Module Definition的縮寫,非同步模塊定義。RequireJS為代表。推崇依賴前置。

//c.js define([./a, ./b], function(a, b){ //a, b依賴在一開始就載入好 a.test(); b.test();})define(id?, deps?, factory) define(function(require, exports, module){ //Your code write here})require([./c], function(c) { //執行回調函數});

非同步載入,只有當依賴模塊載入完畢時,才會執行回調函數。

CMD(2011)

CMD是Common Mudule Definition的縮寫。SeaJS為代表。推崇依賴就近。

define(function(require, exports, module){ //需要時候才載入 var a = require(./a); a.test(); var b = require(./b); b.test();})seajs.use([./a,./b],function(a,b){ //執行回調函數});

UMD(2011)

UMD是Universal Module Definition的縮寫,通用模塊定義。它是AMD和CommonJS的雜糅,希望能同時處理前後端。主要邏輯為:先判斷是否支持Node.js的模塊是否存在,存在則使用CommonJS;再判斷是否支持AMD(define是否存在),存在則使用AMD載入模塊。

(function(root, name, factory){ if (typeof exports === object) { module.exports = factory(); } else if (typeof define === function && define.amd) { define(factory); } else { root[name] = factory(); } }(this, test, function(){ // Your code goes here})

ES6(2015)

ES6終於引入模塊化概念,用簡單的import,export來處理模塊化。不過,ES6尚未被所有瀏覽器支持,只能通過Babel之類的轉譯工具來轉譯。

// a.jsfunction add(x){ return x+1;}export.add = add;// b.jsimport {add} from ./aexport.increase = function(x){ return add(x);}

小結

既然有了JavaScript正室module,我想以後應該就是module的天下了。JavaScript模塊化的問題就得到了完美的解決。當然,目前的方案還是比較簡單,以後應該會更加完善。

介紹了模塊化的基本概況之後,下一篇我會啃一啃模塊化的原理和實現。希望我的智商還夠用~~~

參考資料:

  • JavaScript 模塊演化簡史
  • 理解模塊化
  • js模塊化歷程
  • JavaScript模塊化編程簡史(2009-2016)
  • JavaScript 模塊化入門Ⅰ:理解模塊
  • JavaScript 模塊化入門Ⅱ:模塊打包構建 余博倫
  • github.com/ded/qwery/bl

推薦閱讀:

[譯]Web 的現狀:網頁性能提升指南
[譯] HTTP/2 Server Push 詳解
Vue.js前後端同構方案之準備篇——代碼優化
node.js-腳本合併

TAG:模塊化 | SeaJS | 前端性能優化 |