異步加載是現(xiàn)在已經(jīng)不是一個熱門的話題了。 雖然不熱門了,但他更成為了每一個JSer的基本功。 再次看玉伯博客上推seajs的文章和第一次看的心情已經(jīng)大有不同。特別是玉伯博客 這篇文章。
我學(xué)習(xí)seajs已經(jīng)是3年前的時候了,還記得當(dāng)時看到異步加載覺得很NB。看了那篇文章后覺得seajs ‘a(chǎn)s lazy as possible' 明顯比requirejs 要好...
現(xiàn)在看看評論區(qū)大家就知道兩個東西真正的區(qū)別了。
言歸正傳
用更科學(xué)的方式來區(qū)分amd(requirejs), cmd(seajs), commonJS
首先站在框架設(shè)計者的角度,思考一個模塊加載器要做什么事
0、分析模塊代碼依賴的文件
1、下載文件
2、 JS加載文件
現(xiàn)在我們考慮一種seajs和commonJS中的場景
\\ a.js
if(flag){
require('b');
}else{
require('c');
}
上面代碼 b和c 只有一個會執(zhí)行。 那么我們這兩個文件是否都需要去下載?
動手實踐發(fā)現(xiàn)seaj 把兩個文件都下載了。 但只加載了一個文件。
commonjs因為不需要考慮下載,文件都在本地。所以自然是同步執(zhí)行代碼,用到了再去本地加載執(zhí)行。
再看requireJS的場景
require(['b','c'], function(b,c){
if( flag ){
b();
}else{
c();
}
});
在動手得知, requirejs也是都下載了2個文件,并且b和c都被JS加載了。
這里的加載指的是b和c在使用到之前已經(jīng)是一個對象。
而在seajs中 到 var b = require('b') ;這行之前 b文件只是一個字符串。
requirejs轉(zhuǎn)化為seajs相當(dāng)于
\\ a.js
var b = require('b');
var c = require('c');
...
1000行代碼
...
if(flag){
c();
}else{
b();
}
這兩個的區(qū)別現(xiàn)在就顯而易見了。 requirejs 在模塊被使用到之前就先準備好。 seajs在用到的時候再去準備模塊。
這里我們可以發(fā)現(xiàn)seajs 比 requirejs 少做了沒用的事,更有效率。
但是我們再考慮一種特殊情況比如c模塊中如果會報錯。
那requirejs在一開始就 拋出了錯誤。
而seajs在執(zhí)行到的時候拋出錯誤。
但是! 注意那1000行代碼。 如果c報錯了, 那1000行代碼還有必要執(zhí)行嗎?我們還能回滾那1000行代碼嗎?
這里我們就真正理解了requirejs這樣設(shè)計的原因。seajs用好了能更加極致,用不好就會出上面這種可怕的錯誤。
現(xiàn)在我們已經(jīng)知道設(shè)計一個模塊加載器要做什么和需要注意的點了。
讓我們做個整理。
如果在node端不需要下載文件。 我們則讓代碼同步加載 即Commonjs。
如果在瀏覽器端, 則都需要提早下載文件, 執(zhí)行到一半去下載1秒鐘這可不行。當(dāng)然我們可以提供異步下載的實現(xiàn), require.async 。
下載完文件后是否應(yīng)該先提前準備模塊? 是 AMD, 否CMD。
希望看完你可以知道你需要哪一種了。