難度:中等
Dojo版本:1.7+
原作者:Dylan Schiemann
譯者:Nate (supnate@gmail.com)
原文連結:http://www.sitepen.com/blog/2012/08/27/working-with-dojo-and-amd-in-production/
在最近的一些文章中,我們展示過如何使用嵌套的require來使用通過Dojo Build 系統打包的layer檔案。在這裡,layer是Dojo中的一個術語,一個layer是一個包含了很多JavaScript資源的檔案,即常說的打包後的檔案。從而在生產環境中能夠減少請求次數,提高頁面載入速度。
我們最初是通過如下的語句來實現引入layer檔案的:
<script type="text/javascript" src="../../dojo/dojo.js" data-dojo-config="async: true"></script><script type="text/javascript"> require(['dgrid/dgrid'], function () { require(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/Keyboard", "dojo/_base/declare", "dgrid/test/data/perf", "dojo/domReady!"], function(List, Grid, Selection, Keyboard, declare, testPerfStore){ //...
這樣的寫法固然可以工作,但是並不是很完美。因為你在build之後部署最終的應用的時候需要去修改源檔案。引入一個layer,和在開發過程中require一個普通的AMD Module,寫法是不太一樣的。雖然你可以用PHP或者一些伺服器端語言來產生這樣的javascript檔案,但除此之外,還有很多備選方案。在這我們來看看下面的5種方法:
方法一:單layer的builds
適用於:簡單,快速,單layer的應用
在最初的文章中,我們主要關注如何構建一個簡單並且迷你的包。在現在的情境中,你可能需要建立一個自訂的dojo.js,其中包含了所有你需要的模組。從而我們能夠在頁面的require中一次載入所有需要的模組。我們不需要提前require一個layer,因為所有需要的模組已經通過dojo.js被載入了。
方法二:基於URL來引入不同的模組
適用於:簡單而快速的基於URL格式引入模組
這種方法根據URL來判斷應用應該載入哪些模組。例如,我們可以去判斷URL中是否包含dev這個單詞,從而可以只有在非開發環境時去引入一個額外的模組,即已經打包好的layer。
require(/dev/.test(location.search) ? [] : ['dgrid/dgrid'], function(){ require(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/Keyboard", "dojo/_base/declare", "dgrid/test/data/perf", "dojo/domReady!"], function(List, Grid, Selection, Keyboard, declare, testPerfStore){ //... });});
方法三:配置一個layer的deps和callback
適用於:基於URL或者dojoConfig中的設定去載入相應的模組
Dojo的全域配置中可以設定dojoConfig.deps屬性來載入一個layer,並且在layer載入完成後會自動調用dojoConfig.callback,其中可以放置應用程式啟動的邏輯。
<script type="text/javascript">var dojoConfig = { async: 1, deps: ['dgrid/dgrid'], callback: function(){ require(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/Keyboard", "dojo/_base/declare", "dgrid/test/data/perf", "dojo/domReady!"], function(List, Grid, Selection, Keyboard, declare, testPerfStore){ //... }); }};</script></script type="text/javascript" src="../../dojo/dojo.js"></script>
當相依模組全部載入完成之後,一個回呼函數會被執行,這一切都是在dojoConfig這個對象中定義的。這種情況下我們也可以根據URL來返回相依模組,和之前的例子是類似的。
<script>var dojoConfig = { async: 1, deps: /dev/.test(location.search) ? [] : ['dgrid/dgrid'], callback: function(){ require(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/Keyboard", "dojo/_base/declare", "dgrid/test/data/perf", "dojo/domReady!"], function(List, Grid, Selection, Keyboard, declare, testPerfStore){ //... }); }};</script></script type="text/javascript" src="../../dojo/dojo.js"></script>
這種方法可以靈活的去控制dojoConfig.deps,可以給予URL,或者某個全域變數。甚至我們可以將相依模組作為函數傳回值,從而可以更加靈活的去決定應用程式應該載入什麼樣的模組。
這種靈活的方式可以使我們自由的在開發,測試,以及生產環境之間進行切換。
方法四:頂級模組
適用於:包含非常多模組的大型應用
另一種在開發環境和生產環境間平滑過的常見方法是建立一個頂級模組,在這個頂級模組中去引入某個頁面需要的模組。從而在Dojo Build工具中可以為一個layer僅僅指定這個頂級模組即可,從而開發環境和生產環境都僅需要在HTML中載入同樣的模組。這種方法還有另外一個好處,就是保證了HTML之內沒有JavaScript代碼,從而更加易於維護。
例如,你可能定義了一個模組:app/app.js
define(["dgrid/List", "dgrid/OnDemandGrid","dgrid/Selection", "dgrid/Keyboard", "dojo/_base/declare", "dgrid/test/data/perf", "dojo/domReady!"], function(List, Grid, Selection, Keyboard, declare, testPerfStore){ //...});
然後,你的HTML中僅需要包含下面這段簡單的代碼:
<script>var dojoConfig = { async: true, deps: ["app/app"]};</script><script src="dojo/dojo.js"></script>方法五:Dojo模版項目
適用於:基於Dojo Build最佳實務的一種相當自動的方法
Dojo Boilerplate項目將會自動處理適用於你的情境。它建立了一些Dojo常見應用架構供參考,並且包含了一些自動build指令碼來協助從開發環境過渡到生產環境。
結論
綜上所述,在生產環境中使用AMD和Dojo的layer有很多種方法,你可以根據自己的需求做相應的選擇。當然,如果你有一些其他的好辦法或者問題,歡迎在評論中提出。