模塊加載規(guī)范:CommonJS、AMD 和 CMD,而框架Node.js扎瓶、RequireJS 和 Seajs 分別實現了上述規(guī)范蕊爵。
沒有這些模塊加載規(guī)范時,加載模塊是一種什么情況删铃?
只能在HTML中通過<script>來引入js文件耳贬,同時無法區(qū)分函數來源于哪個js文件,而且要用過多全局變量猎唁。使用模塊加載后咒劲,這些問題都解決了。
CommonJS:
Node.js使用的規(guī)范诫隅,同步加載JS腳本腐魂。在服務端沒問題,因為文件都在磁盤上逐纬。但因為瀏覽器的特性蛔屹,需要異步加載js,否則會失去響應豁生。所以該規(guī)范無法在瀏覽器直接使用判导。
瀏覽器不兼容CommonJS的根本原因嫉父,在于缺少四個Node.js環(huán)境的變量:module、exports眼刃、require绕辖、global
AMD:
Angular.js、require.js使用的規(guī)范擂红,異步加載JS仪际。前置加載,就是在寫主邏輯之前必須指定所有的依賴昵骤,并且等待所有的依賴被異步加載完后執(zhí)行回調函數树碱。依賴的模塊同時被加載,沒有順序依賴变秦。
AMD優(yōu)點:AMD是前置依賴成榜,依賴項最好是已知必須要依賴的,這樣可以一次性將必須用到的JS腳本全部加載蹦玫,后續(xù)可以直接使用赎婚,不需要再遍歷整個函數體查找依賴,提高性能樱溉。
AMD缺點:開發(fā)者必須顯式指明依賴挣输,這會使開發(fā)成本變大,比如當代碼達到幾百上千行的時候福贞,忽然發(fā)現需要增加一個依賴撩嚼,不得不回到函數頂端將依賴添加到數組中。
require(['module1', 'module2'], function(m1, m2){
//主回調邏輯
m1.test();
m2.test();
})
CMD:
Sea.js使用的規(guī)范挖帘。就近加載完丽。Sea.js遇到依賴后,只會去下載JS文件拇舀,等待所有的依賴下載完成后舰涌,再從頭開始執(zhí)行主邏輯。因此被依賴模塊的執(zhí)行順序和書寫順序完全一致你稚。
優(yōu)點:開發(fā)便利瓷耙,動態(tài)加載,可以把依賴寫進代碼任意一行刁赖。
缺點:如下示例代碼搁痛,代碼在運行時是不知道依賴的,需要遍歷所有的require關鍵字宇弛,找到后面的依賴鸡典,具體做法就是將function toString后,用正則匹配出關鍵字后面的依賴枪芒。這是一種犧牲性能來換取開發(fā)便利的方法彻况。
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();
})
}
總結:
對于必須依賴(稱為強依賴)良蛮,如果性能優(yōu)先,可采用AMD前置依賴模式悍赢。
如果開發(fā)成本優(yōu)先决瞳,可采用CMD就近依賴模式。
對于弱依賴左权,只需要將弱依賴的部分改寫到回調函數內即可皮胡。
ES6模塊化:
在 ES6 中,我們使用 export 關鍵字來導出模塊赏迟,使用 import 關鍵字引用模塊屡贺。如果js解析器不識別ES6語法,需要將ES6語法轉換成低版本語法锌杀。目前所有的引擎都還沒有實現import甩栈,我們在node中使用babel支持ES6,也僅僅是將ES6轉碼為ES5再執(zhí)行抛丽,import語法會被轉碼為require。
參考:
寫到這里亿鲜,想起當前做的項目,有很多插件冤吨、配置JS腳本蒿柳,是在HTML通過'<script>'腳本同步引入的,這種寫法很懶省事漩蟆,但會降低性能垒探。看了'<script>'的用法怠李,是可以異步引入的:
1.同步加載<script src="./a.js"></script>
同步模式圾叼,又稱阻塞模式,會阻止瀏覽器的后續(xù)處理捺癞,停止了后續(xù)的解析夷蚊,因此停止了后續(xù)的文件加載(如圖像)、渲染髓介、代碼執(zhí)行惕鼓。
js 之所以要同步執(zhí)行,是因為 js 中可能有輸出 document 內容唐础、修改dom箱歧、重定向等行為矾飞,所以默認同步執(zhí)行才是安全的。
2.帶defer屬性defer屬性聲明這個腳本中將不會有 document.write 或 dom 修改呀邢。瀏覽器將會并行下載 a.js 和其它有 defer 屬性的script洒沦,而不會阻塞頁面后續(xù)處理。注:所有的defer 腳本保證是按順序依次執(zhí)行的驼鹅。
3.帶async屬性<script src="./a.js" async></script>
async屬性是HTML5新增的微谓。作用和defer類似,但是它將在下載后盡快執(zhí)行输钩,不能保證腳本會按順序執(zhí)行豺型。它們將在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 都支持異步加載。
感謝: