提高基于 Dojo 的 Web 2.0 应用程序的性能
Web 2.0 应用以其丰富的用户体验,快捷的响应速度越来越受到众多用户的欢迎。Google Map,Flickr,Yahoo Pipe 等经典的应用都利用了 Web 2.0 的特性。在一些大型的商业软件中,比如 IBM Portal 的新版本也加入了 Web 2.0 的新特性。
从实现的角度来说,一个 Web 2.0 应用最鲜明的特点就是利用了 Ajax 技术来进行异步的数据传输,动态更新@R_301_340@中的某一个 DOM 节点,进行页面局部的刷新,避免了重新加载整个页面,从而使用户能更快的得到响应。
Dojo 作为目前使用最为广泛的一个 Ajax 实现框架,封装了简单易用的 XmlHttpRequest 来进行向后台发送请求,接受响应的操作。Dojo 最让程序员感到方便的就是它提供大量非常实用的 widget,基于 Dojo 提供的这些 widget,程序员可以制作出漂亮的页面,包括一些动画效果等等。
在使用 Dojo,享受它带来的便利的同时,它的性能问题就逐渐暴露出来。比如:当用户第一次加载页面时,会先下载大量的 Dojo 文件到浏览器端,然后再执行这些 Dojo 代码,生成相应的页面,如果您的应用中还使用了 Dojo widget,那还必须要下载这些 widget 对应的 HTML 模板文件和相关的其他资源,有没有什么办法能使下载 Dojo 文件的速度变快一些呢?当在一个页面上使用了大量的 Dojo widget 的时候,Dojo 的加载速度变得比较慢,如何才能让它变快一些呢?
通常一个完整的 Dojo 库大约会有 2M 左右,其中包含了 Dojo 提供的各种 JS 工具方法,核心 IO 框架,Drag&Drop 支持,丰富的 widget 以及其对应的模版和 CSS 文件图片等等。在一个应用中,通常并不会使用到所有的 Dojo 库提供的功能,那么我们就可以通过运行一个 Dojo 发布包里面的命令来定制出一份个性化的 Dojo。
以 Dojo1.0.2 为例,从 Dojo 的官方网站下载一份完整版的 Dojo1.0.2,在 util\buildscripts、profiles 目录下,有很多 *.profile.js 文件,Dojo 默认情况下会采用 base.profile.js 作为 build 的参数,这个文件的内容如下:
清单 1. base.profile.js
|
layers 部分定义可以被直接调用的模块,这些模块所引用到的其他模块也会被加载进来,在 layers 部分不用再次去声明 Dojo 的核心模块比如 dojo.query,它们是被默认加载进来的。layers 是 Dojo 的一种分层机制,它可以把一些松散的 JS 组合成一个 layer,在应用中要使用到相关的 API 时,只要在 <script> 里面声明一下这个 layer 的名字就可以直接在您的 JS 代码中使用这个 layer 中提供的功能。Dojo 在打包整个 Dojo 的代码时,会将这个 layer 中对应的所有 JS 文件进行压缩整理,这样在加载相关 JS 文件的时候,有一定的性能提升。
prefixes 部分用于定义前缀,比如您的 JS 代码在某一个独立于 Dojo 的目录,这里只要您指定一个路径,并给出一个前缀名称,那么在应用中就可以直接用这个前缀来作为这个路径的使用。
开发人员可以根据应用中使用到的 Dojo 特性来做一个对 Dojo 做定制。如何根据一个 profile 文件来定制 Dojo 呢?
在 dojo1.0.2\util\buildscripts 目录中有一个 build.bat 文件,它的作用就是调用 ShrinkSafe 来进行一次 JS 文件的压缩,并做适当优化。
关于该 build 命令的使用方法,这里仅介绍几个常用的参数。
表 1. Build 主要参数及用途
参数名称 | 参数用途 |
---|---|
profile | 指定 profile 文件的名称,如要指定 base.profile.js,设定 profile = base 即可 |
action | 指定本次命令的类型,提供的三个值是:clean,release,help |
releaseName | 指定本次 release 的名字,默认是 dojo |
optimize | 指定进行优化的方式,Dojo 提供四种优化方式: |
一个典型的定制 Dojo 的命令可以如下:
$ build.sh profile=base action=release releaseName=myDojo optimize=shrinksafe |
通常在一个 Web 2.0 应用中,会有很多业务逻辑相关的 JS 代码,而且很多逻辑从后台搬到了客户端执行,因此这部分客户端代码非常多。为了提供更快的响应速度,典型的做法是压缩所有客户端需要加载的资源包括图片,HTML 文件,CSS 文件,JS 代码等等,而图片文件已经无法再进行压缩,只有 HTML,CSS,JS 等文本文件有进一步压缩的空间。
进行文本文件压缩的工具比较多,这里重点介绍 shrinksafe,在定制 Dojo 的过程中,可以指定 shrinksafe 作为压缩 Dojo 内部文件的方式。就是说 Dojo 已经自带了一份 shrinksafe 实现。在 Dojo 1.0.2 中有一个 jar 文件:dojo1.0.2\util\shrinksafe\ custom_rhino.jar,这是一个基于 rhino 实现的压缩工具,关于 rhino 有兴趣的读者请查阅参考资料部分。
shrinksafe 之所以称其“safe”,是因为它在压缩了 JS 文件以后,不会改变其对象内部方法和属性名称,引用到该段代码的地方不需要任何更改,还是可以直接调用其内部方法和属性。 在 custom_rhino.jar 所在的目录运行java –jar custom_rhino.jar –version 100
可以进入 rihno 的命令行状态。
图 1. custom_rhino 运行参数
压缩一个 JS 文件的命令如下:
java -jar custom_rhino.jar -c infile.js > outfile.js |
经测试,一个 JS 文件经过这样的命令压缩后,可以减小 30% 左右,将压缩后的文件放回系统中,对该 JS 文件的功能调用没有任何影响。
当页面上有大量的 Dojo widget 或者自定义 widget,页面的加载和解析会变的比较慢,Dojo 系统的一些默认参数可能是导致这些现象的原因。通过改变这些参数,我们可以看到页面的加载和解析速度有了明显改善。
Dojo 在默认情况下会搜索整个 DOM 树,判断当前的 DOM 节点是不是 widget,如果是就开始加载该 widget 的 JS,HTML,CSS 等资源。在页面上 DOM 节点非常庞大时,这显然是一个很大的开销。Dojo 提供了系统参数 parseWidgets 和 searchIds 让用户来指定是否只对某些 DOM 节点进行解析。
在应用启动的页面中加入如下定义:
<script> djConfig = { parseWidgets: false,searchIds: [] }; </script> |
如果确定在某些节点以及其内部不会有 widget 出现,那么在该节点上加上这样一个属性:
<div parseWidgets="false"> 内部无 widget </div> |
当某些节点确定是 widget,一定要让 Dojo 来解析该节点,将该节点加入 searchIds:
<div dojoType="Menu" id="menyu1">...</div> <script>djConfig.searchIds.push("menu1");</script> |
某些通过用户的操作以后才会显示或者创建出来的内容,可以不放在初始页面上,而仅放一个 placeholder 在页面中,典型的例子就是 Dojo 的 tab widget。
清单 2. Dojo TabContainer
<div dojoType="TabContainer"> <a dojoType="LinkPane" href="tab1.jsp">Tab #1</a> <a dojoType="LinkPane" href="tab2.jsp">Tab #2</a> </div> |
采用这样的定义,就可以避免加载@R_301_340@时就 load tab1 或者 tab2 里的内容。
减少 DOM 树中的节点,当页面中内容非常多时,响应速度必然会变慢,因此应该尽量将一些无用的 DOM 节点删除或者简化,下面是个极端的例子 :
清单 3. 复杂的 DOM 节点
< table > < tr > <td> Hello World </td> < /tr > </ table > |
更简单的定义方式是一个 div 加上相应的 css:
<div class="foo">Hello World</div> |
当前针对 Firefox 和 IE 的性能检测工具有很多,这里分别对 Firefox 和 IE 各推荐一些工具。
在 Firefox 里面,firebug 是首选的工具,它是一款比较轻量级的 Firefox 插件,它可以监测发送的每个请求到达的 url 以及响应完成的时间。同时它还可以灵活地动态修改 DOM 节点,CSS 等,并实时显示出修改后的效果。
图 2. Firebug 监控 HTTP 请求
图 3. Firebug 修改 DOM 节点
这是 IEWatch 公司开发的一款商业产品,是一个 IE 插件,提供了对 HTML 和 HTTP 的状态分析。它列出了加载@R_301_340@过程中所发出的请求以及各个请求的响应时间。但是对 HTML 的状态跟踪以及 DOM 节点展现方式不太灵活。
图 4. IEWatch 监控 HTTP 请求
图 5. IEWatch 修改 DOM 节点
IE Developer Toolbar 也是一款不错的 IE 调试工具,是 Microsoft 自己提供的 IE 插件,它能将当前 DOM 树以树状结构展现。Microsoft 官方推荐的是 Microsoft Script Editor,Microsoft Script Debugger。
本文介绍了几种提高基于 Dojo 的 Web 2.0 应用的性能的方式,包括如何定制一个自定义的 Dojo build,如何使用 shrinksafe 压缩应用中的 JS 文件,以及如何配置 Dojo 参数使之更高效的解析 DOM 树,最后还介绍了几种比较常用的调试工具。
- 参考Dojo Toolkit 官方网站。
- 参考ShrinkSafe 简介。
- 参考Rhino 文档。
- 参考Dean Edwards' Packer。
- 阅读 developerWorks 文章:“使用 Dojo 和 DB2 开发 Ajax Web 应用程序”。
- 阅读 developerWorks 文章:“如何在 Domino 上使用 Ajax 框架 Dojo”。
- 了解Firebug。
- 了解IEWatch。
- 了解IE Developer Toolbar。
施伟,IBM 中国开发中心软件工程师,您可以通过shiwcsdl@cn.ibm.com与他联系。