咱們來玩樂高積木吧html
模塊化Js已經成爲了老生常談,不過在JavaScript設計之初,因爲定位的問題並無提供類的功能,開發者須要模擬出相似的功能,來隔離、組織複雜的JavaScript代碼。以前的閉包也好,自執行函數也好,都是模塊化的一些嘗試,直到CommonJs
規範推出以後,模塊化Js才真正迅猛發展起來。node
從時間點上來講:瀏覽器
Node遵循CommonJs
模塊化規範,NPM
包管理系統發展如此迅猛就是CommonJs
模塊化規範的最佳實踐緩存
後來在CommonJs
的基礎上衍生出了AMD/CMD
規範,其各自的實踐分別是RequireJS
和SeaJs
服務器
CommonJs規範遵循的是同步加載模塊規範,即:網絡
var A = require(./module/a); A.funA(); var B = require(./module/b); B.funB();
即只有a.js加載完之後,才能接着向下執行A.funA();
才能接着向下加載b.js, 等b.js加載完以後,才能向下執行B.funB();
。但這種同步串行的加載方式確對效率並無多大影響,由於CommonJs
是在Node上運行,處於服務器環境,服務器環境對模塊的加載等同於硬盤的讀寫速度,是很是很是快的。閉包
AMD/CMD
遵循的是異步加載模塊規範,拿CMD
規範的SeaJs
舉例:異步
define(function(require,exports,module){ require.async('./module/a', function(){alert(1)} require.async('./module/b', function(){alert(2)} });
其中,alert(1) 和alert(2)的執行順序是不固定的,由於是採用異步加載模塊的方式,a模塊和b模塊是並行加載的 ,誰先加載完畢,誰先掉用回調. 由於網絡和文件大小的緣由, 固然有多是b模塊先加載完畢,因此多是alert(2)先執行.async
由於requireJs(AMD)
和SeaJs(CMD)
都是運行在客戶端瀏覽器上的. 模塊的加載速度和網絡情況有關係,加載狀況是很是不穩定,若是採用同步串行加載的方式,會出現由於前面的模塊加載耗時太長而阻塞了它以後的模塊的加載. 因此AMD/CMD
纔有了異步的解決方案模塊化
(固然,AMD/CMD
也支持同步加載)
按需加載是模塊化Js引申出來的概念.咱們可讓特定的頁面加載特定的JS,就像搭積木恰好把房子搭起來同樣,用Js模塊組合的方式能夠項目搭建起來,保證不缺乏任何一個必要的模塊,也保證不會有任何一個多餘的模塊.
若是index.html只須要彈窗功能和滑動功能,就只加載pop.js和slip.js
提及來卻是挺簡單,但實際上呢?
實際上也很是簡單,拿seaJS
舉例來講,頁面index.html引用了Sea.js後,就能夠以index.js爲加載入口,對頁面所需的七七八八的JS模塊進行加載:
index.html:
<script src="static/js/lib/sea.js" id="seaJSnode"></script> <script> seaJS.use("./index.js"); </script>
其中index.js:
define(function(require,exports,module){ //引入模塊a var A = require('./module/a'); //引入模塊b var B = require('./module/b') ... });
其中a.js又依賴了其餘的模塊:
define(function(require,exports,module){ //引入模塊c var C = require('./module/c'); ... });
無論這個依賴關係有多複雜,層級有多深,seaJS的模塊加載器會遞歸找到全部頁面index.html依賴的Js,就拿例子來講,和index.html有關的依賴有 入口文件index.js
和它依賴的a.js, b.js
,而且還有a.js
依賴的 c.js
因此最後index.html實際上會加載index.js, a.js, b.js , c.js
這樣就實現了頁面須要什麼模塊,就加載什麼模塊(和這些模塊依賴的模塊),從而實現了按需加載。
但有同窗估計又想到了,這個地方有個小缺陷,雖然模塊化Js使得加載邏輯更清晰了,可是如此碎片化的Js會增長頁面http的請求數,從而影響頁面的加載速度。
沒錯,因此咱們一般在上線前會利用自動化工具對當前頁面依賴的全部Js作一個合併處理,即合併壓縮成一個Js文件, 這樣能最大程度上的利用瀏覽器緩存,減小Http請求數。
(注:Js模塊書寫的時候請儘可能避免循環引用的問題,即a.js
引用了c.js
,反過來c.js
又引用了a.js
. 這確定是模塊書寫不規範形成的,請檢查這兩個模塊的邏輯是否有重疊. 固然,除此以外循環引用仍是有別的辦法解決的,這裏就不提了)
總而言之,模塊化Js目前有兩大規範(固然要說成三種規範也能夠,不過在做者本人看來AMD/CMD並無本質上的區別)
CommonJS
同步加載模塊規範,運行在服務端
AMD/CMD
異步加載模塊規範,運行在客戶端
由於CommonJs規範在服務器端的同步串行加載Js模塊的方式並不適用於客戶端瀏覽器,因此纔有了AMD/CMD規範延伸出異步並行加載Js模塊的方式。
由於有了Js模塊化的概念,纔有了Js按需加載的概念。