模塊加載規范:CommonJS、AMD 和 CMD,而框架Node.js、RequireJS 和 Seajs 分別實現了上述規范。
沒有這些模塊加載規范時,加載模塊是一種什么情況?
只能在HTML中通過<script>來引入js文件,同時無法區分函數來源于哪個js文件,而且要用過多全局變量。使用模塊加載后,這些問題都解決了。
CommonJS:
Node.js使用的規范,同步加載JS腳本。在服務端沒問題,因為文件都在磁盤上。但因為瀏覽器的特性,需要異步加載js,否則會失去響應。所以該規范無法在瀏覽器直接使用。
瀏覽器不兼容CommonJS的根本原因,在于缺少四個Node.js環境的變量:module、exports、require、global
AMD:
Angular.js、require.js使用的規范,異步加載JS。前置加載,就是在寫主邏輯之前必須指定所有的依賴,并且等待所有的依賴被異步加載完后執行回調函數。依賴的模塊同時被加載,沒有順序依賴。
AMD優點:AMD是前置依賴,依賴項最好是已知必須要依賴的,這樣可以一次性將必須用到的JS腳本全部加載,后續可以直接使用,不需要再遍歷整個函數體查找依賴,提高性能。
AMD缺點:開發者必須顯式指明依賴,這會使開發成本變大,比如當代碼達到幾百上千行的時候,忽然發現需要增加一個依賴,不得不回到函數頂端將依賴添加到數組中。
require(['module1', 'module2'], function(m1, m2){
//主回調邏輯
m1.test();
m2.test();
})
CMD:
Sea.js使用的規范。就近加載。Sea.js遇到依賴后,只會去下載JS文件,等待所有的依賴下載完成后,再從頭開始執行主邏輯。因此被依賴模塊的執行順序和書寫順序完全一致。
優點:開發便利,動態加載,可以把依賴寫進代碼任意一行。
缺點:如下示例代碼,代碼在運行時是不知道依賴的,需要遍歷所有的require關鍵字,找到后面的依賴,具體做法就是將function toString后,用正則匹配出關鍵字后面的依賴。這是一種犧牲性能來換取開發便利的方法。
define(function(require, exports, module){
var foo= require('foo');//同步加載
foo.add(1, 2);
require.async('math', fucntion(math){//異步加載
math.add(1,2);
})
});
上面對AMD和CMD說的都是必須依賴(可稱為強依賴)的情況,還有一些依賴,是在特定條件成立后才需要加載的(可稱為弱依賴)。
if(status){a.doSomething()}
這種情況可以用異步回調方式實現:
AMD實現:if(status){
async(['a'], function(a){
a.doSomething();
})
}
CMD實現:if(status){
require.async('a', function(a){
?a.doSomething();
})
}
總結:
對于必須依賴(稱為強依賴),如果性能優先,可采用AMD前置依賴模式。
如果開發成本優先,可采用CMD就近依賴模式。
對于弱依賴,只需要將弱依賴的部分改寫到回調函數內即可。
ES6模塊化:
在 ES6 中,我們使用 export 關鍵字來導出模塊,使用 import 關鍵字引用模塊。如果js解析器不識別ES6語法,需要將ES6語法轉換成低版本語法。目前所有的引擎都還沒有實現import,我們在node中使用babel支持ES6,也僅僅是將ES6轉碼為ES5再執行,import語法會被轉碼為require。
參考:
寫到這里,想起當前做的項目,有很多插件、配置JS腳本,是在HTML通過'<script>'腳本同步引入的,這種寫法很懶省事,但會降低性能。看了'<script>'的用法,是可以異步引入的:
1.同步加載<script src="./a.js"></script>
同步模式,又稱阻塞模式,會阻止瀏覽器的后續處理,停止了后續的解析,因此停止了后續的文件加載(如圖像)、渲染、代碼執行。
js 之所以要同步執行,是因為 js 中可能有輸出 document 內容、修改dom、重定向等行為,所以默認同步執行才是安全的。
2.帶defer屬性defer屬性聲明這個腳本中將不會有 document.write 或 dom 修改。瀏覽器將會并行下載 a.js 和其它有 defer 屬性的script,而不會阻塞頁面后續處理。注:所有的defer 腳本保證是按順序依次執行的。
3.帶async屬性<script src="./a.js" async></script>
async屬性是HTML5新增的。作用和defer類似,但是它將在下載后盡快執行,不能保證腳本會按順序執行。它們將在onload 事件之前完成。
defer屬性在IE 4.0中就實現了,超過13年了!Firefox 從 3.5 開始支持defer屬性 。
Firefox 3.6、Opera 10.5、IE 9 和 最新的Chrome 和 Safari 都支持 async 屬性。可以同時使用 async 和 defer,這樣IE 4之后的所有 IE 都支持異步加載。
感謝: