就在前天晚上RequireJS發布了一個大版本,直接從version1.0.8升級到了2.0。隨后的幾小時James Burke又迅速的將版本調整為2.0.1,當然其配套的打包壓縮工具r.js也同時升級到了2.0.1。此次變化較大,代碼也進行了重構,層次更清晰可讀。功能上主要變化如下:
1,延遲模塊的執行。
這是一個很大變化,以前模塊加載后factory立馬執行。性能上肯定有一些損耗。2.0修改實現,再沒人詬病AMD的模塊是立即執行的。現在也可以等到require的時候才執行。
2,config增加了shim,map,module,enforceDefine。
shim參數解決了使用非AMD方式定義的模塊(如jQuery插件)及其載入順序。使用shim參數來取代1.0版本的order插件。其實在1.0版本中就曾經有人開發過use和wrap插件來解決此類問題。考慮到很多開發者有此類需求(比如某些JS模塊是較早時候其他人開發的,非AMD方式)此次2.0版本直接將其內置其中。
下面是一個使用jQuery插件形式配置的參數。我們知道jQuery插件本質上是將命名空間掛在全局的jQuery或jQuery.fn上而非使用define定義的模塊。而jQuery插件都依賴於jQuery,即在require插件時得保證jQuery先下載下來。可以如下配置
require.config({ shim: { 'jquery-slide': ['jquery'] } }); require(['jquery-slide']);
這時會保證先下載jquery.js,然后再下載jquery-slide.js。
map參數用來解決同一個模塊的不同版本問題,這一靈感來自於Dojo的packageMap。有這樣的場景:開發初期使用了的jquery-1.6.4,后期升級到了1.7.2。但擔心有些依賴jquery-1.6.4的代碼升級到1.7.2后有問題。因此保守的讓這部分代碼繼續使用1.6.4版本。這時map參數將派上用場。
假如A,B模塊中使用了jquery-1.6.4.js,C,D模塊中使用了jquery-1.7.2.js。如下
requirejs.config({ map: { 'A': { 'jquery': 'jquery-1.6.4' }, 'B': { 'jquery': 'jquery-1.7.2' } } }); require(['A']); // download jquery-1.6.4.js require(['B']); // download jquery-1.7.2.js
這時require(['A'])將會下載jquery-1.6.4.js,require(['B'])會下載jquery-1.7.2.js。模塊“A”如果寫成“*”則表示除了B模塊使用jquery-1.7.2之外其它模塊都使用jquery-1.6.4。map參數解決了模塊的各個版本問題,很好的向下兼容了老代碼。
config參數用來給指定的模塊傳遞一些有用的數據。如下
require.config({ config: { 'A': { info: {name: 'jack'} } } });
使用A的模塊中可以通過A.config().info獲取到該數據信息。如
require(['A'], function(A) { var info = A.config().info; console.log(info); });
enforceDefine用來強制模塊使用define定義,默認為false。如underscore不再支持AMD后,其代碼移除了define。此時如果仍然使用requirejs來載入它,它就是普通的js文件了。此時如果enforceDefine設為true,雖然underscore.js能下載但requirejs會報錯。如
require.config({ enforceDefine: true }); require(['underscore'], function(_){ console.log(_) })
錯誤信息
4,require函數增加了第三個參數errbacks。
很明顯該函數指模塊文件沒有載入成功時的回調。這個也是應一些開發者得要求而增加,其中還包括另一個著名AMD的實現curl的作者John Hann。
require(['b'], function(){ console.log('success'); },function(err){ console.log(err) });
err會給出一些出錯提示信息。
5,更強大的paths參數。
requirejs 1.x版本中已經有paths參數,用來映射模塊別名。requirejs2.0更加強大,可以配置為一個數組,順序映射。當前面的路徑沒有成功載入時可接着使用后面的路徑。如下
requirejs.config({ enforceDefine: true, paths: { jquery: [ 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min', 'lib/jquery' ] } }); require(['jquery'], function ($) { });
當google cdn上的jquery.min.js沒有獲取時(假如google宕機),可以使用本地的lib/jquery.js。
6,在模塊載入失敗回調中可以使用undef函數移除模塊的注冊。
這個靈感來自dojo AMD loader,RequireJS取名undef。如下
require(['jquery'], function ($) { //Do something with $ here }, function (err) { var failedId = err.requireModules && err.requireModules[0]; if (failedId === 'jquery') { requirejs.undef(failedId); } });
7,刪除了jQuery domready相關代碼。
這次沒人再詬病RequireJS和jQuery耦合的太緊密。
8,刪除了priority,packagePaths,catchError.define。
這幾個參數已經有相應的替代品。
最后需要注意的是,雖然功能增加了不少。但代碼量卻減少了近60行。主要是去掉了jQuery ready相關代碼。另外newContext函數依然有1000多行。