提高基于 Dojo 的 Web 2.0 应用程序的性能


</p>

Web 2.0 应用程序最注重的一个方面就是用户体验,用户希望使用的是一个快速稳定的 Web 2.0 应用。而基于 Dojo 的 Web 2.0 应用经常需要下载大量 Dojo 代码到客户端执行,而且会不时的向后台发起 IO 请求,响应速度受到很大影响。本文通过演示一些实用的技巧来提高 Dojo 的性能,帮助开发人员找出 Web 2.0 应用程序的性能瓶颈。

Web 2.0 Dojo 介绍

Web 2.0 应用以其丰富的用户体验,快捷的响应速度越来越受到众多用户的欢迎。Google Map,Flickr,Yahoo Pipe 等经典的应用都利用了 Web 2.0 的特性。在一些大型的商业软件中,比如 IBM Portal 的新版本也加入了 Web 2.0 的新特性。

从实现的角度来说,一个 Web 2.0 应用最鲜明的特点就是利用了 Ajax 技术来进行异步的数据传输,动态更新当前页面中的某一个 DOM 节点,进行页面局部的刷新,避免了重新加载整个页面,从而使用户能更快的得到响应。

Dojo 作为目前使用最为广泛的一个 Ajax 实现框架,封装了简单易用的 XmlHttpRequest 来进行向后台发送请求,接受响应的操作。Dojo 最让程序员感到方便的就是它提供大量非常实用的 widget,基于 Dojo 提供的这些 widget,程序员可以制作出漂亮的页面,包括一些动画效果等等。

在使用 Dojo,享受它带来的便利的同时,它的性能问题就逐渐暴露出来。比如:当用户第一次加载页面时,会先下载大量的 Dojo 文件到浏览器端,然后再执行这些 Dojo 代码,生成相应的页面,如果您的应用中还使用了 Dojo widget,那还必须要下载这些 widget 对应的 HTML 模板文件和相关的其他资源,有没有什么办法能使下载 Dojo 文件的速度变快一些呢?当在一个页面上使用了大量的 Dojo widget 的时候,Dojo 的加载速度变得比较慢,如何才能让它变快一些呢?

解决 Dojo 性能问题的常见技巧

定制和压缩 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

dependencies = {

layers: [

{

name: "../dijit/dijit.js",

resourceName: "dijit.dijit",

dependencies: [

"dijit.dijit"

]

},

{

name: "../dijit/dijit-all.js",

resourceName: "dijit.dijit-all",

layerDependencies: [

"../dijit/dijit.js"

],

dependencies: [

"dijit.dijit-all"

]

},

{

name: "../dojox/off/offline.js",

resourceName: "dojox.off.offline",

layerDependencies: [

],

dependencies: [

"dojox.off.offline"

]

}

],

prefixes: [

[ "dijit","../dijit" ],

[ "dojox","../dojox" ]

]

}

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 提供四种优化方式:

  • comments:仅删掉代码的注释 ;
  • shrinksafe:使用 Dojo compressor 来进行代码的压缩 ;
  • shrinksafe.keepLines:使用 Dojo compressor 来进行代码的压缩,但是代码换行会被保留 ;
  • packer:使用 Dean Edwards' Packer 这种压缩工具进行代码压缩。

一个典型的定制 Dojo 的命令可以如下:

$ build.sh profile=base action=release releaseName=myDojo optimize=shrinksafe

压缩其他 JS 文件

通常在一个 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 系统参数

当页面上有大量的 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>

采用这样的定义,就可以避免加载当前页面时就 load tab1 或者 tab2 里的内容。

其它 Tip

减少 DOM 树中的节点,当页面中内容非常多时,响应速度必然会变慢,因此应该尽量将一些无用的 DOM 节点删除或者简化,下面是个极端的例子 :

清单 3. 复杂的 DOM 节点

< table >

< tr >

<td> Hello World </td>

< /tr >

</ table >

更简单的定义方式是一个 div 加上相应的 css:

<div class="foo">Hello World</div>


回页首

检测性能瓶颈的工具

当前针对 Firefox 和 IE 的性能检测工具有很多,这里分别对 Firefox 和 IE 各推荐一些工具。

Firebug

在 Firefox 里面,firebug 是首选的工具,它是一款比较轻量级的 Firefox 插件,它可以监测发送的每个请求到达的 url 以及响应完成的时间。同时它还可以灵活地动态修改 DOM 节点,CSS 等,并实时显示出修改后的效果。

2. Firebug 监控 HTTP 请求

3. Firebug 修改 DOM 节点

IEWatch

这是 IEWatch 公司开发的一款商业产品,是一个 IE 插件,提供了对 HTML 和 HTTP 的状态分析。它列出了加载当前页面过程中所发出的请求以及各个请求的响应时间。但是对 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 树,最后还介绍了几种比较常用的调试工具。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易知道用户保存了什么,我希望当用户第一次看到网格时,网格处于不可编辑状态.当用户准备好后,他们可以单击编辑按钮,这将使网格的某些部分可编辑.然后,有一个保存或取消按钮可以保存更改或还原.在大多数情况下它是有效的.但
我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以轻松打包为Web,Mobiles和可能的Standalone版本的方式来实现这一目标.我不想使用Flash.因此,我确信(无论如何我会听取建议)使用JavaScript和SVG.我正在对这个问题进行大量研究,但我很难把各个部分放在一起.我知道Raphae
我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部件–我在表单中使用–将固定格式(JavaScript基本格式)的实数值(例如:12.56)设置为HTML表单输入字段(但根据浏览器区域设置显示/编辑它们,所以用户总是看到格式正确的数字).另一方面,Grails期望输入字段根据浏览器
1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforjavaScript的学习历程,本篇将从最开始的arcgisapiforjavaScript部署开始,个人声明:博文不在传道受业解惑,旨在方便日后复习查阅。由于是自学,文章中可能会出现一些纰漏,请留言指出,不必留有情面哦!2.下载ArcGISforDe
我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑:Thedeclarefunctionisdefinedinthedojo/_base/declaremodule.declareacceptsthreearguments:className,superClass,andproperties.ClassNameTheclassNameargumentrepresentsthenameofthec
我的团队由更多的java人员和JavaScript经验丰富组成.我知道这个问题曾多次被问到,但为了弄清楚我的事实,我需要澄清一些事情,因为我在客户端技术方面的经验非常有限.我们决定使用GWT而不是纯JavaScript框架构建我们的解决方案(假设有更多的Java经验).这些是支持我的决定的事实.>
路由dojo/framework/srcouting/README.mdcommitb682b06ace25eea86d190e56dd81042565b35ed1Dojo应用程序的路由路由FeaturesRoute配置路径参数RouterHistoryManagersHashHistoryStateHistoryMemoryHistoryOutletEventRouterContextInjectionOutl
请原谅我的无知,因为我对jquery并不熟悉.是否有dojo.connect()的等价物?我找到了这个解决方案:http:/hink-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/但是没有断开功能!你知道jquery的其他解决方案吗?有jquery.connect但这个插件在我的测试中不起作用.
与java类一样,在dojo里也可以定义constructor 构造函数,在创建一个实例时可以对需要的属性进行初始化。//定义一个类mqsy_yjvar mqsy_yj=declare(null,{     //thedefaultusername    username: "yanjun",          //theconstructor   
我一直在寻找一些最佳实践,并想知道Dojo是否具有框架特定的最佳实践,还是最好只使用通用的Javascript标准?特别是我主要是寻找一些功能和类评论的指导方针?解决方法:对于初学者来说,这是项目的风格指南:DojoStyleGuide
我有’05/17/2010’的价值我想通过使用dojo.date.locale将其作为“2010年5月17日”.我尝试过使用dojo.date.locale.parse,如下所示:x='05/17/2010'varx=dojo.date.locale.parse(x,{datePattern:"MM/dd/yyyy",selector:"date"});alert(x)这并没有给我所需的日期
我正在尝试创建一个包含函数的dojo类,这些函数又调用此类中的其他函数,如下所示:dojo.provide("my.drawing");dojo.declare("my.drawing",null,{constructor:function(/*Object*/args){dojo.safeMixin(this,args);this.container=args[0];
我知道你可以使用jQuery.noConflict为jQuery做这件事.有没有办法与Dojo做类似的事情?解决方法:我相信你可以.有关在页面上运行多个版本的Dojo,请参阅thispage.它很繁琐,但似乎是你正在寻找的东西.一般来说,Dojo和jQuery都非常小心,不会破坏彼此或其他任何人的变量名.
我有一个EnhancedGrid,用户经常使用复杂的过滤器.有没有办法允许用户保存或标记过滤器,以便将来可以轻松地重新应用它?我知道我可以通过编程方式设置过滤器,但我无法预测用户想要的过滤器.谢谢!编辑:自己做了一些进展…使用grid.getFilter()返回过滤器的JSON表示,然后使用json.strin
我有这个代码:dojo.declare("City",null,{constructor:function(cityid,cityinfo){}});dojo.declare("TPolyline",GPolyline,{constructor:function(points,color){},initialize:function(map){});应该是什
我遇到的问题是我的所有javascript错误似乎来自dojo.xd.js或子模块.我正在使用chrome调试器和许多dijit功能,如dijit.declaration和dojo.parser.这有点烦人,因为它很难找到简单的错误或滑倒.我希望我可以添加一个选项,允许我的调试器在我的非dojo代码中显示选项会发生的位置.我是
我正在使用DojoToolkit数字/解析函数来处理格式化和使用ICU模式语法解析字符串.有没有人知道有可能采取任意ICU模式字符串并以某种方式使用Dojo(或其他)库将其分解为它的部分(例如,对于数字模式,它可以被分解为小数位数,数千个分组等…).我希望这样做,而不需要让我的代码密切了
我有两个看似相关的问题,访问在不同的地方定义的javascript函数.我遇到的第一个问题是调用我在firgbug或safari控制台中定义的函数.我定义了一个名为getRed的函数,如下所示:functiongetRed(row,col){//dosomethingstuffandreturntheredvalueasa
我想添加一个在Ajax调用中指定的外部样式表.我已经找到了一种方法来使用jQuery(参见下面的示例),但是我需要使该方法适应dojoJavaScript框架.JQuery示例$('head').append('<linkrel="stylesheet"type="text/css"href="lightbox_stylesheet.css">');谢谢.解决方法:一旦你
我正在尝试使用dojo.connect将onMouseDown事件连接到图像,如:dojo.connect(dojo.byId("workpic"),"onMouseDown",workpicDown);functionworkpicDown(){alert("mousedown");}类似的代码几行后,我将onMouse*事件连接到dojo.body确实完全正常工作.但是当我点击图像时