小記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 模塊化入門Ⅱ:模塊打包構建 余博倫
- https://github.com/ded/qwery/blob/master/src/qwery.js
推薦閱讀:
※[譯]Web 的現狀:網頁性能提升指南
※[譯] HTTP/2 Server Push 詳解
※Vue.js前後端同構方案之準備篇——代碼優化
※node.js-腳本合併