何時我們需要 Dojo 的 build 工具
Dojo 作為一個非常實用的 Ajax 實現框架已經被許多 web2.0 開發人員廣泛使用,但使用 Dojo 會導致客戶端瀏覽器需要加載大量的 Dojo 文件,導致應用程序性能下降。解決 Dojo 性能問題的方法之一就是對 Dojo 文件進行定制打包和壓縮 ( 提高 Dojo 性能的具體方案請參看“提高基于 Dojo 的 Web 2.0 應用程序的性能”。Dojo 本身已經提供了一套對 Dojo 庫文件 ( 自己編寫的 Javascript 文件只要符合 Dojo 的規范同樣可以進行打包 ) 進行 build 的工具,通過定制庫文件和壓縮文件的方法來減少瀏覽器加載文件的時間。
Dojo 的主要庫文件 (dojo 包 ) 大小在 1M 左右,dijit 包和 dojox 包大小都在 4M-5M,但我們并不總是需要所有的這些庫文件,可以根據開發者自身的需要定制一份 Dojo 庫,實際使用的庫文件大小往往能大大降低;以筆者目前的開發項目為例,經過定制后實際使用的 Dojo 庫文件大小只有 300K 左右。
另外 Dojo 的 build 工具也通過壓縮 Javascript 文件的手段來降低瀏覽器加載文件的時間(該過程中需要使用 ShrinkSafe,有關其詳細介紹請參看“http://dojotoolkit.org/docs/shrinksafe”),具體的方法如下:
- 壓縮 Javascript 文件,包括:
- 刪除所有的空格和空行
- 刪除所有的注釋
- 將定義變量名用更簡短的字符代替
- 將所有打包的的 Javascript 文件的內容合并為一個文件
經過壓縮處理,Javascript 文件的大小總體可減少 30%-50%,同時將所有的 Javascript 文件打包成一個文件也減少了瀏覽器加載時多次開閉文件的負擔,從而降低了加載時間。
準備工作
- 到“dojo 下載網站”下載 Dojo 源代碼,下載后直接解壓即可,設 Dojo 的解壓目錄為 \dojo(下文中皆用“\dojo”指代 Dojo 文件的解壓目錄);
- 下載并安裝 JDK( 盡量使用 1.5 以上的版本 ),設置 JAVA_HOME 環境變量;
jdk 下載地址:http://java.sun.com/javase/downloads/index.jsp
使用 Dojo 的 build 工具
Dojo 提供的 build 工具位于 \dojo\util\buildsrcipts 下,在 windows 下調用該目錄內的 build.bat(linux 下使用 build.sh)文件既可執行 build 工作。
下面是在一個在 windows 下調用 build.bat 的例子:
build profile=base action=release releaseName=myDojo optimize=shrinksafe
該命令中包括了幾個最常用的參數,其意義如下:
- action: 指定本次命令的類型,提供的三個值是:clean, release, help;
- releaseName:本次 release 的名字,默認為 dojo;
- optimize:本次 build 中進行優化的方式,一般使用 shrinksafe 既可;
- profile:指定 build 使用的 profile 文件,profile 文件中提供了 build 相關的配置信息,在 \dojo\util\buildsrcipts\profiles 目錄下有很多 *.profile.js 文件,我們自定義的 profile 文件也放在這個目錄下,例子中“profile=base”表示指定 base.profile.js 作為 build 的參數。
實際上在使用 Dojo 的 build 工具時,關鍵在于提供的 profile 文件里的內容,在下面的例子中會詳細說明 profile 文件的配置方法。
定制 Dojo 文件
Dojo 庫中提供了大量的文件供使用者調用,但有的時候我們并不是需要所有的這些文件,此時我們可以使用 Dojo 的 build 工具定制一份個性化的 Dojo 庫文件,首先我們需要編寫一個 profile 文件來描述我們的需求:
清單 1. profile 文件配置示例 1
/* example.profile.js */ dependencies = { layers: [ // 可以根據需要制定多個不同的 layer { name: "example.js", // 打包生成的 js 文件的名 dependencies: [ // 需要打包的 js 文件列表 "dojo.date", "dojox.uuid" ] } ], prefixes: [ // 設置路徑 [ "dijit", "../dijit" ], [ "dojox", "../dojox" ] ] }
注意:
- dojo.js 是默認被打包的,不需要在 dependencies中聲明
- 在 prefixes 設置路徑應該是相對 dojo\dojo\dojo.js 的路徑,../dijit 實際上是 dojo\dijit
將該文件 (example.profile.js) 放在 \dojo\util\buildsrcipts\profiles 目錄下,執行:
build profile=example action=release releaseName=myDojo optimize=shrinksafe
build 完成后,會在 \dojo 下生成一個 release 文件夾,如下圖所示:
圖示 1. build 后釋放的文件示意:

因為我們設置了 build 的參數 releaseName=myDojo, 因此 release 下會生成一個 myDojo 文件夾,本次 build 產生的文件都置于該文件夾下。在 \dojo\release\myDojo\dojo\ 目錄下,我們可以找到兩個文件:example.js 和 example.uncompressed.js,這就是我們需要的打包后的文件,example.uncompressed.js 只是包含了我們指定的所有 dojo 文件,example.js 則在 example.uncompressed.js 基礎上又進行了壓縮處理。
build 我們自己的 Javascript 文件
對于我們自己編寫的 Javascript 文件,我們同樣可是借助 Dojo 提供的 build 工具進行壓縮和打包,前提是這些 js 文件需要按照 Dojo 相關的的規范編寫。打包我們自己的 Javascript 文件與打包 Dojo 文件并沒有太大的差別,假設我們有兩個 Javascript 文件如下:
清單 2. 假設需要打包的 2 個 Javascript 文件
/* my.example1 */ dojo.provide("my.example1"); dojo.require("my.example2"); // 聲明了對 my.example2 的依賴 /* * this is a js file witch named example1.js */ /* my.example2 */ dojo.provide("my.example2"); /* * this is a js file witch named example2.js */
在 \dojo 下新建一個文件夾“my”, 將上面的兩個文件放在該文件夾下,profile 文件配置如下:
清單 3. profile 文件配置示例 2
/* example.profile.js */ dependencies = { layers: [ { name: "example.js", dependencies: [ "dojo.date", "dojox.uuid", "my.example1" // 注意這里我們只聲明了 my.example1 ] } ], prefixes: [ [ "dijit", "../dijit" ], [ "dojox", "../dojox" ], [ "my", "../my"] // 剛才新建的 my 文件夾需要在此聲明路徑 ] }
執行:
build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe
請注意,在 profile 文件中,只聲明了將 my.example1 進行打包,但在 build 生成的 example.js 中我們會發現 my.example2 中的內容也已經被添加進來了。這是因為在 build 過程中,build 程序在分析 js 文件內容時通過識別一些關鍵字 ( 例如 dojo.require) 來判斷當前文件是否依賴其他的文件,并將這些依賴的文件一同進行打包。因此當 build 程序在 my.example1 中讀到 dojo.require("my.example2"); 時,判斷出該文件需要依賴另一個文件"my.example2",根據 prefixes 提供的路徑 build 程序找到了 my.example2.js 文件,并將該文件的內容添加進來。
按照上面的例子 build 后,我們自己編寫的 Javascript 文件會和我們定制 Dojo 的文件合并在一個文件中,我們可能需要獨立使用這些自己編寫的 Javascript 文件,那么我們修改一下 profile 文件既可:
清單 4. profile 文件配置示例 3
/* example.profile.js */ dependencies = { layers: [ { // 這個 layer 用來打包我們定制的 dojo 文件 name: "mydojo.js", dependencies: [ "dojo.date", "dojox.uuid" ] }, { // 這個 layer 用于打包我們自己的 js 文件 name: "example.js", dependencies: [ "my.example1" ] } ], prefixes: [ [ "dijit", "../dijit" ], [ "dojox", "../dojox" ], [ "my", "../my"] ] }
執行:
build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe
這樣 build 后在 \dojo\release\myDojo\dojo\ 我們會分別得到 mydojo 和 example 兩個 layer 的打包文件:
- mydojo.js 和 mydojo.uncompressed.js:打包的是我們定制的 Dojo 文件
- example.js 和 example.uncompressed.js:打包了我們自己編寫 Javascript 文件,我們可以根據需要獨立使用他們
需要注意的問題
- 在上面我們已經講到了 build 程序會按照 dojo.require 等關鍵字將依賴文件添加進來,因此在每個 layer 的 dependencies 中我們不必列出所有我們需要打包的文件,只需要將一些根文件列出既可 ( 如清單 3 所示 );另外我們也應該確保這些需要打包的文件以及他們所依賴的其他文件所在的路徑都在 prefixes 聲明注冊過,否則 build 程序會因為找不到所需要的文件而失敗。
- 上面提到在 build 過程中,會調用 shrinksafe 將 js 文件進行壓縮,壓縮策略包括將定義的變量名用更為簡潔的字符串替代,例如我們定義
”var identifier”
,經過壓縮處理可能就變成了”var _v01”
,。如果我們的 Javascript 代碼中使用了eval
語句,并且eval
的內容里包含了一些我們定義的變量名,就會導致打包后的文件出現錯誤而無法使用。例如下面的 Javascript 代碼:
var identifier = “”; eval(“alert(identifier)”);
因為經過壓縮后變量名 identifier 被 build 程序以其他的名字替代,因此在執行 eval 方法 , 也就是調用 alert(identifier) 時,會因為無法識別 identifier 而報出 undefined 的錯誤。
小結
本文站在一個初學者的角度簡單地介紹了 Dojo 的 build 工具的使用方法(關鍵在于 profile 文件的配置),通過以上內容讀者應該能夠使用該工具進行基本的定制和打包處理,有興趣的讀者可以通過提供的參考資料進行進一步的學習。