何时我们需要 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 文件的配置),通过以上内容读者应该能够使用该工具进行基本的定制和打包处理,有兴趣的读者可以通过提供的参考资料进行进一步的学习。