如果一个页面需要js动态引入jsp页面十多个js怎么去优化

在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
优化的方向应该是减少http请求次数,那么可以使用webpack打包压缩成一个js文件
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。雅虎十四条:网站前端网页优化的14条原则-马海祥博客
新型SEO思维就是从一个全新的层次上提升seo优化的水平,达到网络信息最佳化的展示效果!
> 雅虎十四条:网站前端网页优化的14条原则
雅虎十四条:网站前端网页优化的14条原则
时间:&&&文章来源:马海祥博客&&&访问次数:
内容再丰富的网站,如果慢到无法访问也是毫无意义的;SEO做的再好的网站,如果搜索蜘蛛抓不到也是白搭;UE设计的再人性化的网站,如果用户连看都看不到也是空谈。
所以,网页的效率优化绝对是最值得关注的方面,那么,我们该如何才能提高一个网页的效率呢?对此,我今天就在马海祥博客上为大家分享一下雅虎网页优化的14条原则,也被称为:雅虎十四条,而这些原则也是我们作为一名SEO人员所必须了解的。
1、减少HTTP请求次数
据统计,有80%的最终用户响应时间是花在前端程序上,而其大部分时间则花在各种页面元素,如图像、样式表、脚本和Flash等的下载上,减少页面元素将会减少HTTP请求次数,这是快速显示页面的关键所在。
一种减少页面元素个数的方法是简化页面设计,但是否存在其他方式,能做到既有丰富内容,又能获得快速响应时间呢?以下是这样一些技术:
Image maps组合多个图片到一张图片中,总文件大小变化不大,但减少了HTTP请求次数从而加快了页面显示速度(具体可查看马海祥博客《》的相关介绍),该方式只适合图片连续的情况,同时坐标的定义是烦人又容易出错的工作。
CSS Sprites是更好的方法,它可以组合页面中的图片到单个文件中,并使用CSS的background-image和background-position属性来现实所需的部分图片。
Inline images使用data:URL scheme来在页面中内嵌图片,这将增大HTML文件的大小,组合inline images到你的(缓存)样式表是既能较少HTTP请求,又能避免加大HTML文件大小的方法。
Combined files通过组合多个脚本文件到单一文件来减少HTTP请求次数,样式表也可采用类似方法处理,这个方法虽然简单,但没有得到大规模的使用。
据马海祥博客收集的资料显示:国外10大网站每页平均有7个脚本文件和2个样式表,当页面之间脚本和样式表变化很大时,该方式将遇到很大的挑战,但如果做到的话,将能加快响应时间。
减少HTTP请求次数是性能优化的起点,这最提高首次访问的效率起到很重要的作用,据Tenni Theurer的文章Browser Cache Usage - Exposed描述,40-60%的日常访问是首次访问,因此为首次访问者加快页面访问速度是用户体验的关键。
对此,马海祥的建议是:将首页的几十个小图标合并为一个,通过CSS控制它们的显示,减少了HTTP请求数。
2、使用CDN(Content Delivery Network,内容分发网络)
用户离web server的远近对响应时间也有很大影响,从用户角度看,把内容部署到多个地理位置分散的服务器上将有效提高页面装载速度,但是该从哪里开始呢?
作为实现内容地理分布的第一步,不要试图重构web应用以适应分布架构,改变架构将导致多个周期性任务,如同步session状态,在多个server之间复制数据库交易,这样缩短用户与内容距离的尝试可能被应用架构改版所延迟或阻止。
我们还记得80-90%的最终用户响应时间花在下载页面中的各种元素上,如图像文件、样式表、脚本和Flash等,与其花在重构系统这个困难的任务上,还不如先分布静态内容,这不仅能大大减少响应时间,而且由于CDN的存在,分布静态内容非常容易实现。
CDN是地理上分布的web server的集合,用于更高效地发布内容,通常基于网络远近来选择给具体用户服务的web server。
一些大型网站拥有自己的CDN,但是使用如Akamai Technologies、Mirror Image Internet或Limelight Networks等CDN服务提供商的服务将是划算的,在Yahoo!把静态内容分布到CDN减少了用户影响时间20%或更多,切换到CDN的代码修改工作是很容易的,但能达到提高网站的速度。
对此,马海祥的建议是:目前还没用到,不过据客户反映,广东山东等地网络情况比较差,如果可以将占据主要带宽的静态资源通过CDN发布,相信可以大大缓解目前网站访问速度的问题。
3、增加Expires Header
网页内容正变得越来越丰富,这意味着更多的脚本文件、样式表、图像文件和Flash,首次访问者将不得不面临多次HTTP请求,但通过使用Expires header,您可以在客户端缓存这些元素,这在后续访问中避免了不必要的HTTP请求,Expires header最常用于图像文件,但是它也应该用于脚本文件、样式表和Flash。
浏览器(和代理)使用缓存来减少HTTP请求的次数和大小,使得网页加速装载,Web server通过Expires header告诉客户端一个元素可以缓存的时间长度。
如果服务器是Apache的话,您可以使用ExpiresDefault基于当期日期来设置过期日期,如:ExpiresDefault &access plus 10 years&,设置过期时间为从请求时间开始计算的10年。
请记住,如果使用超长的过期时间,则当内容改变时,您必须修改文件名称,在Yahoo!我们经常把改名作为release的一个步骤:版本号内嵌在文件名中,如yahoo_2.0.6.js。
对此,马海祥的建议是:在Apache配置了JS,CSS,image的缓存,如果静态资源需要更新,则采用修改文件版本号的方案确保客户端取得最新版本。
4、压缩页面元素
通过压缩HTTP响应内容可减少页面响应时间,从HTTP/1.1开始,web客户端在HTTP请求中通过Accept-Encoding头来表明支持的压缩类型,如:Accept-Encoding: gzip,deflate.
如果Web server检查到Accept-Encoding头,它会使用客户端支持的方法来压缩HTTP响应,会设置Content-Encoding头,如:Content-Encoding: gzip。
Gzip是目前最流行及有效的压缩方法,其他的方式如deflate,但它效果较差,也不够流行。通过Gzip,内容一般可减少70%;如果是Apache,在1.3版本下需使用mod_gzip模块,而在2.x版本下,则需使用mod_deflate。
Web server根据文件类型来决定是否压缩,大部分网站对HTML文件进行压缩,但对脚本文件和样式表进行压缩也是值得的,实际上,对包括XML和JSON在内的任务文本信息进行压缩都是值得的,图像文件和PDF文件不应该被压缩,因为它们本来就是压缩格式保存的,对它们进行压缩,不但浪费CPU,而且还可能增加文件的大小。
因此,对尽量多的文件类型进行压缩是一种减少页面大小和提高用户体验的简便方法。
对此,马海祥的建议是:600多K的ext2包,是人都会想到要去压缩它,压缩后的效果还不错,只有150多K,另外,JS、CSS、HTML也尽量压缩(在此也推荐一种压缩CSS代码的简单工具:),要知道我们的很多客户还在使用1M的ADSL。
5、把样式表放在头上
无论是HTML还是XHTML还是CSS都是解释型的语言,而非编译型的,所以CSS到上方的话,那么浏览器解析结构的时候,就已经可以对页面进行渲染,这样就不会出现,页面结构光秃秃的先出来,然后CSS渲染,页面又突然华丽起来,这样太具有&戏剧性&的页面浏览体验了。
我们发现把样式表移到HEAD部分可以提高界面加载速度,因此这使得页面元素可以顺序显示。
在很多浏览器下,如IE,把样式表放在document的底部的问题在于它禁止了网页内容的顺序显示,浏览器阻止显示以免重画页面元素,那用户只能看到空白页了,Firefox不会阻止显示,但这意味着当样式表下载后,有些页面元素可能需要重画,这导致闪烁问题。
HTML规范明确要求样式表被定义在HEAD中,因此,为避免空白屏幕或闪烁问题,最好的办法是遵循HTML规范,把样式表放在HEAD中。
对此,马海祥的建议是:目前还没有碰到把样式表放在文档后面的情况吧?
6、把脚本文件放在底部
与样式文件一样,我们需要注意脚本文件的位置,我们需尽量把它们放在页面的底部,这样一方面能顺序显示,另方面可达到最大的并行下载。
浏览器会阻塞显示直到样式表下载完毕,因此我们需要把样式表放在HEAD部分,而对于脚本来说,脚本后面内容的顺序显示将被阻塞,因此把脚本尽量放在底部意味着更多内容能被快速显示。
脚本引起的第二个问题是它阻塞并行下载数量,HTTP/1.1规范建议浏览器每个主机的并行下载数不超过2个,因此如果您把图像文件分布到多台机器的话,您可以达到超过2个的并行下载,但是当脚本文件下载时,浏览器不会启动其他的并行下载,甚至其他主机的下载也不启动。
在某些情况下,不是很容易就能把脚本移到底部的,如,脚本使用document.write方法来插入页面内容,同时可能还存在域的问题,不过在很多情况下,还是有一些方法的。
一个备选方法是使用延迟脚本(deferred script),DEFER属性表明脚本未包含document.write,指示浏览器刻继续显示,不幸的是,Firefox不支持DEFER属性,在IE中,脚本可能被延迟执行,但不一定得到需要的长时间延迟。
不过,从另外角度来说,如果脚本能被延迟执行,那它就可以被放在底部了。
对此,马海祥的建议是:这点之前大家可能都没有意识到,不过在我们的XCube XUI中我们已经实施了这条法则,相信可以进一步提升页面的访问性能。
7、避免CSS表达式
CSS表达式是功能强大的(同时也是危险的)用于动态设置CSS属性的方式,IE从版本5开始支持CSS表达式,如backgourd-color: expression((new Date()).getHours()%2?&#B8D4FF&:&#F08A00&),即背景色每个小时切换一次。
CSS表达式的问题是其执行次数超过大部分人的期望,不仅页面显示和resize时计算表达式,而且当页面滚屏,甚至当鼠标在页面上移动时都会重新计算表达式。
一种减少CSS表达式执行次数的方法是一次性表达式,即当第一次执行时就以明确的数值代替表达式,如果必须动态设置的话,可使用事件处理函数代替,如果您必须使用CSS表达式的话,请记住它们可能被执行上千次,从而影响页面性能(具体可查看马海祥博客《》的相关介绍)。
对此,马海祥的建议是:目前CSS的维护工作主要由UI人员负责,他们已经尽量在避免这种情况了。
8、把JavaScript和CSS放到外部文件中
上述很多性能优化法则都基于外部文件进行优化,现在,我们必须问一个问题:JavaScript和CSS应该包括在外部文件,还是在页面文件中?
在现实世界中,使用外部文件会加快页面显示速度,因为外部文件会被浏览器缓存,如果内置JavaScript和CSS在页面中虽然会减少HTTP请求次数,但增大了页面的大小。
另外一方面,使用外部文件,会被浏览器缓存,则页面大小会减小,同时又不增加HTTP请求次数。
因此,一般来说,外部文件是更可行的方式,唯一的例外是内嵌方式对主页更有效,如Yahoo!和My Yahoo!都使用内嵌方式,一般来说,在一个session中,主页访问此时较少,因此内嵌方式可以取得更快的用户响应时间。
对此,马海祥的建议是:ext2的代码作了很好的引导,目前前端开发人员都非常注意客户端模块的封装、重用,尽量以外部JS的方式提高代码的重用度,当然也要注意不要引入过多的外部资源,因为这违反了法则1。
目前CSS的封装也不错,但是主要是针对IE系列的解决方案,可以考虑引入YAML、blueprint等CSS框架,轻松解决浏览器兼容性问题。
另外,马海祥要提醒大家一点:把JavaScript和css文件放到外部,并不内嵌于网页,同时可以考虑把样式表放到头上把脚本文件放到底部。需要注意的是尽量不要使用css的表达式,他很容易让浏览器出现假死。
9、减少DNS查询次数
DNS用于映射主机名和IP地址,一般一次解析需要20~120毫秒,为达到更高的性能,DNS解析通常被多级别地缓存,如由ISP或局域网维护的caching server,本地机器操作系统的缓存(如windows上的DNS Client Service),浏览器,IE的缺省DNS缓存时间为30分钟,Firefox的缺省缓冲时间是1分钟。
减少主机名可减少DNS查询的次数,但可能造成并行下载数的减少,避免DNS查询可减少响应时间,而减少并行下载数可能增加响应时间,一个可行的折中是把内容分布到至少2个,最多4个不同的主机名上。
对此,马海祥的建议是:为了绕开浏览器对下载线程数的限制,我们对静态资源启用了多域名,但是这么做违反了该法则,不过,对windows IE来说,DNS的缓存可以缓解该问题。
10、最小化JavaScript代码
最小化JavaScript代码指在JS代码中删除不必要的字符,从而降低下载时间,两个流行的工具是#JSMin和YUI Compressor。
混淆是最小化于源码的备选方式,象最小化一样,它通过删除注释和空格来减少源码大小,同时它还可以对代码进行混淆处理,作为混淆的一部分,函数名和变量名被替换成短的字符串,这使得代码更紧凑,同时也更难读,使得难于被反向工程,Dojo Compressor (ShrinkSafe)是最常见的混淆工具。
最小化是安全的、直白的过程,而混淆则更复杂,而且容易产生问题,从对国外10大网站的调查来看,通过最小化,文件可减少21%,而混淆则可减少25%(具体可查看马海祥博客《》的相关介绍)。
除了最小化外部脚本文件外,内嵌的脚本代码也应该被最小化,即使脚本根据法则4被压缩后传输,最小化脚本刻减少文件大小5%或更高。
对此,马海祥的建议是:我们没有直接使用JS压缩,但是我们用的许多组件例如ext2、jquery等,已经在为我们实践该法则。
11、避免重定向
重定向功能是通过301和302这两个HTTP状态码完成的,如:
HTTP/1.1 301 Moved Permanently
  Location: http://mahaixiang.cn/newuri
  Content-Type: text/html
浏览器自动重定向请求到Location指定的URL上,重定向的主要问题是降低了用户体验。
一种最耗费资源、经常发生而很容易被忽视的重定向是URL的最后缺少/,如访问http://www.mahaixiang.cn/astrology将被重定向到http://www.mahaixiang.cn/astrology/,在Apache下,可以通过Alias,mod_rewrite或DirectorySlash等方式来解决该问题。
经验丰富的SA已经为我们考虑了这个问题,对此,马海祥的建议是:大家可以看看线上环境的Apache配置文件:httpd.conf。
12、删除重复的脚本文件
在一个页面中包含重复的JS脚本文件会影响性能,即它会建立不必要的HTTP请求和额外的JS执行。
不必要的HTTP请求发生在IE下,而Firefox不会产生多余的HTTP请求,额外的JS执行,不管在IE下,还是在Firefox下,都会发生。
一个避免重复的脚本文件的方式是使用模板系统来建立脚本管理模块,除了防止重复的脚本文件外,该模块还可以实现依赖性检查和增加版本号到脚本文件名中,从而实现超长的过期时间。
对此,马海祥的建议是:旧版本的Xplatform中这个问题比较严重,不过相信新版的XCube不会重蹈覆辙。
另外,提醒大家一点:一些javascript框架、javascript包一定要慎用,至少要问一下:用了这个js kit到底给我们多少方便,提高了多少工作效率,然后,再与它因为多余的、重复的代码带来的负面效果比较一下。
13、配置ETags
Etag(Entity tags)实体标签,这个tag和你在网上经常看到的标签云那种tag有点区别,这个Etag不是给用户用的,而是给浏览器缓存用的。
Etag是服务器告诉浏览器缓存,缓存中的内容是否已经发生变化的一种机制,通过Etag,浏览器就可以知道现在的缓存中的内容是不是最新的,需不需要重新从服务器上重新下载,这和&Last-Modified&的概念有点类似,很遗憾作为网页开发人员对此无能为力,他依然是网站服务器人员的工作范畴。
ETags是用于确定浏览器缓存中元素是否与Web server中的元素相匹配的机制,它是比last-modified date更灵活的元素验证机制。
ETag是用于唯一表示元素版本的字符串,它需被包括在引号中,Web server首先在response中指定ETag:
HTTP/1.1 200 OK
  Last-Modified: Tue, 12 Dec :59 GMT
  ETag: &10c24bc-4ab-457e1c1f&
  Content-Length: 12195
后来,如果浏览器需要验证某元素,它使用If-None-Match头回传ETag给Web server,如果ETag匹配,则服务器返回304代码,从而节省了下载时间:
GET /i/yahoo.gif HTTP/1.1
  Host: mahaixiang.cn
  If-Modified-Since: Tue, 12 Dec :59 GMT
  If-None-Match: &10c24bc-4ab-457e1c1f&
  HTTP/1.1 304 Not Modified
ETags的问题在于它们是基于服务器唯一性的某些属性构造的,如Apache1.3和2.x,其格式是inode-size-timestamp,而在IIS5.0和6.0下,其格式是Filetimestamp:ChangeNumber。
这样同一个元素在不同的web server上,其ETag是不一样的,在多Web server的环境下,浏览器先从server1请求某元素,后来向server2验证该元素,由于ETag不同,所以缓存失效,必须重新下载。
因此,如果您未用到ETags系统提供的灵活的验证机制,最好删除ETag,删除ETag会减少http response及后续请求的HTTP头的大小,微软支持文章描述了如何删除ETags,而在Apache下,只要在配置文件中设置FileETag none即可。
对此,马海祥的建议是:自定义ETag的生成策略,以尽量减少探头规则的生成次数,由于不是采用服务器默认的ETag,不存在该问题,如果以前没有关注过的,赶快检查一下Apache中的配置。
14、缓存Ajax
现在的Ajax好像有点被神话了,好像网页只要Ajax了,那么就不存在效率问题了,其实这是一种误解,拙劣的使用Ajax不会让你的网页效率更高,反而会降低你的网页效率。
在马海祥看来,Ajax的确是个好东西,但是请不要过分的神话它,使用Ajax的时候也要考虑上面的那些准则。
另外,性能优化法则同样适用于web 2.0应用,提高Ajax的性能最重要的方式是使得其response可缓存,就象&法则3增加Expires Header&讨论的那样,以下其他法则同样适用于Ajax,当然法则3是最有效的方式。
马海祥博客点评:
网页设计和SEO技术结合是网络技术发展对网页设计师的新要求,95%的SEO技巧很简单,而最重要的5%是&经验&、&创意&和&人脉&,需要在工作中根据实际情况不断做出调整策略,并持之以恒地把SEO优化坚持下去。
本文为原创文章,如想转载,请注明原文网址摘自于http://www.mahaixiang.cn/znseo/1056.html,注明出处;否则,禁止转载;谢谢配合!
您可能还会对以下这些文章感兴趣!
网络实名制是个长期以来争议不断的话题。一方面,当人们面对越来越多的网上低俗与不良信息、黑客与木马、网……
最近百度跟360的搜索引擎之争,也使得更多人开始关注搜索引擎了,回想搜索引擎的快速发展也就是近15年发生……
清明节又叫踏青节,在仲春与暮春之交,也就是冬至后的第108天。是中国传统节日,也是最重要的祭祀节日之一……
很多做SEO的朋友都会问,是不是网站收录越多网站关键字排名越好……
最近,我明显发现访问马海祥seo博客的博友越来越多了,随之而来……
最近一直听到圈里的朋友抱怨说,自己辛辛苦苦写的文章,发表的前……
作为一名专业的SEO人员,我们很多的时候都在研究站点中有多少页……
由于此次整理的SEO作弊方法大全的内容比较多,也比较全面,导致……
相信做个seo的,或者自己已经是站长的,都或多或少的对自己负责……
本月热点文章下次自动登录
现在的位置:
& 综合 & 正文
一个项目中对页面进行优化
  原为单个jsp页面。本来打算是把这18个jsp页面,做成一个主页面。左侧菜单,右侧主体置空后,替换为iframe。点击不同的链接,通过传参给一个js函数,来更改iframe的src,以及页面的banner图片、当前位置等(也有打算用ajax实现,但是用ajax还需要生成一个xmlhttp对象,多了一个步骤,不采用)。解决了如iframe高度自适应等问题(有的页面有有十几个点击隐藏显示div的操作,给iframe高度自适应带来了麻烦,但是通过主页面给iframe的onload设置高度初始值解决了。)
  一切顺利,但是问题是,从外部页面,进入主页后,然后又在主页通过点击链接更改了页面,点击刷新总是不能定位到当前显示的页面,而是跑到主页面。后来通过1、js传参+一个隐藏的input。2、把当前页面状态id传到剪贴板等,然后设置body的onbeforeload来解决,在firefox下,正常,在IE下不行,因为IE能检测到刷新事件,但是它只执行刷新事件中的系统函数,无法执行自定义的函数。
  又想了个办法,把当前页面状态id设到cookie中。果然IE、FIREFOX都正常,但是又有了新的问题,万一用户COKKIE关闭了不是又完了。
  最后,只有采用直接的方法,把链接改为直接的href链接,而不是执行某函数。这样通过网址传参给自身页面,然后用js得到参数的方式进行设定iframe的src、BANNER等,解决了改问题。
  这种方式只是在一个页面转来转去,和点击链接通过js函数更改页面局部的方式,在FIREFOX的yslow中的评分都是A,原为C,原载入量为150K左右,目前的经检测载入量除第一次150K外,其它全部只有十几,小几十K。所以也没原来想的糟糕,而且更简单。也更利于以后的cms的引进。
同时优化的还有
1、去除prototype.js,因为只使用了它的ajax功能,就把它去掉,自己写了个ajax创建函数,节省了70k。
2、把一些色彩单调的图片转为gif格式,也节省了几十k。
3、去除一些talbe,嵌套太多,去除一些,有的全部去掉,用padding和margin来达到同样的目的。
后台页面也优化了一部分:主要是1、去除&/s:head&,用它,这个页面,就会成倍膨胀。2、有些图片,被上层东西遮盖。遮盖的部分就给去掉。3、dxhtml的两个js及一个css移至只使用它们的页面,而不是放在使用ajax的首页。4、jquery.js替换为压缩版的。
&&&&推荐文章:
【上篇】【下篇】JavaScript 的性能优化:加载和执行
无论当前 JavaScript 代码是内嵌还是在外链文件中,页面的下载和渲染都必须停下来等待脚本执行完成。JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。一个典型的例子就是在页面中使用document.write()。例如清单 1清单 1 JavaScript 代码内嵌示例&html&
&title&Source Example&/title&
&script type="text/javascript"&
document.write("Today is " + (new Date()).toDateString());
&/html&当浏览器遇到&script&标签时,当前 HTML 页面无从获知 JavaScript 是否会向&p& 标签添加内容,或引入其他元素,或甚至移除该标签。因此,这时浏览器会停止处理页面,先执行 JavaScript代码,然后再继续解析和渲染页面。同样的情况也发生在使用 src 属性加载 JavaScript的过程中,浏览器必须先花时间下载外链文件中的代码,然后解析并执行它。在这个过程中,页面渲染和用户交互完全被阻塞了。脚本位置HTML 4 规范指出 &script& 标签可以放在 HTML 文档的&head&或&body&中,并允许出现多次。Web 开发人员一般习惯在 &head& 中加载外链的 JavaScript,接着用 &link& 标签用来加载外链的 CSS 文件或者其他页面信息。例如清单 2清单 2 低效率脚本位置示例&html&
&title&Source Example&/title&
&script type="text/javascript" src="script1.js"&&/script&
&script type="text/javascript" src="script2.js"&&/script&
&script type="text/javascript" src="script3.js"&&/script&
&link rel="stylesheet" type="text/css" href="styles.css"&
&p&Hello world!&/p&
&/html&然而这种常规的做法却隐藏着严重的性能问题。在清单 2 的示例中,当浏览器解析到 &script& 标签(第 4 行)时,浏览器会停止解析其后的内容,而优先下载脚本文件,并执行其中的代码,这意味着,其后的 styles.css 样式文件和&body&标签都无法被加载,由于&body&标签无法被加载,那么页面自然就无法渲染了。因此在该 JavaScript 代码完全执行完之前,页面都是一片空白。图 1 描述了页面加载过程中脚本和样式文件的下载过程。图 1 JavaScript 文件的加载和执行阻塞其他文件的下载我们可以发现一个有趣的现象:第一个 JavaScript 文件开始下载,与此同时阻塞了页面其他文件的下载。此外,从 script1.js 下载完成到 script2.js 开始下载前存在一个延时,这段时间正好是 script1.js 文件的执行过程。每个文件必须等到前一个文件下载并执行完成才会开始下载。在这些文件逐个下载过程中,用户看到的是一片空白的页面。从 IE 8、Firefox 3.5、Safari 4 和 Chrome 2 开始都允许并行下载 JavaScript 文件。这是个好消息,因为&script&标签在下载外部资源时不会阻塞其他&script&标签。遗憾的是,JavaScript 下载过程仍然会阻塞其他资源的下载,比如样式文件和图片。尽管脚本的下载过程不会互相影响,但页面仍然必须等待所有 JavaScript 代码下载并执行完成才能继续。因此,尽管最新的浏览器通过允许并行下载提高了性能,但问题尚未完全解决,脚本阻塞仍然是一个问题。由于脚本会阻塞页面其他资源的下载,因此推荐将所有&script&标签尽可能放到&body&标签的底部,以尽量减少对整个页面下载的影响。例如清单 3清单 3 推荐的代码放置位置示例&html&
&title&Source Example&/title&
&link rel="stylesheet" type="text/css" href="styles.css"&
&p&Hello world!&/p&
&!-- Example of efficient script positioning --&
&script type="text/javascript" src="script1.js"&&/script&
&script type="text/javascript" src="script2.js"&&/script&
&script type="text/javascript" src="script3.js"&&/script&
&/html&这段代码展示了在 HTML 文档中放置&script&标签的推荐位置。尽管脚本下载会阻塞另一个脚本,但是页面的大部分内容都已经下载完成并显示给了用户,因此页面下载不会显得太慢。这是优化 JavaScript 的首要规则:将脚本放在底部。组织脚本由于每个&script&标签初始下载时都会阻塞页面渲染,所以减少页面包含的&script&标签数量有助于改善这一情况。这不仅针对外链脚本,内嵌脚本的数量同样也要限制。浏览器在解析 HTML 页面的过程中每遇到一个&script&标签,都会因执行脚本而导致一定的延时,因此最小化延迟时间将会明显改善页面的总体性能。这个问题在处理外链 JavaScript 文件时略有不同。考虑到 HTTP 请求会带来额外的性能开销,因此下载单个 100Kb 的文件将比下载 5 个 20Kb 的文件更快。也就是说,减少页面中外链脚本的数量将会改善性能。通常一个大型网站或应用需要依赖数个 JavaScript 文件。您可以把多个文件合并成一个,这样只需要引用一个&script&标签,就可以减少性能消耗。文件合并的工作可通过离线的打包工具或者一些实时的在线服务来实现。需要特别提醒的是,把一段内嵌脚本放在引用外链样式表的&link&之后会导致页面阻塞去等待样式表的下载。这样做是为了确保内嵌脚本在执行时能获得最精确的样式信息。因此,建议不要把内嵌脚本紧跟在&link&标签后面。无阻塞的脚本减少 JavaScript 文件大小并限制 HTTP 请求数在功能丰富的 Web 应用或大型网站上并不总是可行。Web 应用的功能越丰富,所需要的 JavaScript 代码就越多,尽管下载单个较大的 JavaScript 文件只产生一次 HTTP 请求,却会锁死浏览器的一大段时间。为避免这种情况,需要通过一些特定的技术向页面中逐步加载 JavaScript 文件,这样做在某种程度上来说不会阻塞浏览器。无阻塞脚本的秘诀在于,在页面加载完成后才加载 JavaScript 代码。这就意味着在 window 对象的 onload事件触发后再下载脚本。有多种方式可以实现这一效果。延迟加载脚本HTML 4 为&script&标签定义了一个扩展属性:defer。Defer 属性指明本元素所含的脚本不会修改 DOM,因此代码能安全地延迟执行。defer 属性只被 IE 4 和 Firefox 3.5 更高版本的浏览器所支持,所以它不是一个理想的跨浏览器解决方案。在其他浏览器中,defer 属性会被直接忽略,因此&script&标签会以默认的方式处理,也就是说会造成阻塞。然而,如果您的目标浏览器支持的话,这仍然是个有用的解决方案。清单 4 是一个例子清单 4 defer 属性使用方法示例&script type="text/javascript" src="script1.js" defer&&/script&带有 defer 属性的&script&标签可以放置在文档的任何位置。对应的 JavaScript 文件将在页面解析到&script&标签时开始下载,但不会执行,直到 DOM 加载完成,即onload事件触发前才会被执行。当一个带有 defer 属性的 JavaScript 文件下载时,它不会阻塞浏览器的其他进程,因此这类文件可以与其他资源文件一起并行下载。任何带有 defer 属性的&script&元素在 DOM 完成加载之前都不会被执行,无论内嵌或者是外链脚本都是如此。清单 5 的例子展示了defer属性如何影响脚本行为:清单 5 defer 属性对脚本行为的影响&html&
&title&Script Defer Example&/title&
&script type="text/javascript" defer&
alert("defer");
&script type="text/javascript"&
alert("script");
&script type="text/javascript"&
window.onload = function(){
alert("load");
&/html&这段代码在页面处理过程中弹出三次对话框。不支持 defer 属性的浏览器的弹出顺序是:“defer”、“script”、“load”。而在支持 defer 属性的浏览器上,弹出的顺序则是:“script”、“defer”、“load”。请注意,带有 defer 属性的&script&元素不是跟在第二个后面执行,而是在 onload 事件被触发前被调用。如果您的目标浏览器只包括 Internet Explorer 和 Firefox 3.5,那么 defer 脚本确实有用。如果您需要支持跨领域的多种浏览器,那么还有更一致的实现方式。HTML 5 为&script&标签定义了一个新的扩展属性:async。它的作用和 defer 一样,能够异步地加载和执行脚本,不因为加载脚本而阻塞页面的加载。但是有一点需要注意,在有 async 的情况下,JavaScript 脚本一旦下载好了就会执行,所以很有可能不是按照原本的顺序来执行的。如果 JavaScript 脚本前后有依赖性,使用 async 就很有可能出现错误。动态脚本元素文档对象模型(DOM)允许您使用 JavaScript 动态创建 HTML 的几乎全部文档内容。&script&元素与页面其他元素一样,可以非常容易地通过标准 DOM 函数创建:清单 6 通过标准 DOM 函数创建&script&元素var script = document.createElement ("script");
script.type = "text/javascript";
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);新的&script&元素加载 script1.js 源文件。此文件当元素添加到页面之后立刻开始下载。此技术的重点在于:无论在何处启动下载,文件的下载和运行都不会阻塞其他页面处理过程。您甚至可以将这些代码放在&head&部分而不会对其余部分的页面代码造成影响(除了用于下载文件的 HTTP 连接)。当文件使用动态脚本节点下载时,返回的代码通常立即执行(除了 Firefox 和 Opera,他们将等待此前的所有动态脚本节点执行完毕)。当脚本是“自运行”类型时,这一机制运行正常,但是如果脚本只包含供页面其他脚本调用调用的接口,则会带来问题。这种情况下,您需要跟踪脚本下载完成并是否准备妥善。可以使用动态 &script& 节点发出事件得到相关信息。Firefox、Opera, Chorme 和 Safari 3+会在&script&节点接收完成之后发出一个 onload 事件。您可以监听这一事件,以得到脚本准备好的通知:清单 7 通过监听 onload 事件加载 JavaScript 脚本var script = document.createElement ("script")
script.type = "text/javascript";
//Firefox, Opera, Chrome, Safari 3+
script.onload = function(){
alert("Script loaded!");
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);Internet Explorer 支持另一种实现方式,它发出一个 readystatechange 事件。&script&元素有一个 readyState 属性,它的值随着下载外部文件的过程而改变。readyState 有五种取值:
“uninitialized”:默认状态
“loading”:下载开始
“loaded”:下载完成
“interactive”:下载完成但尚不可用
“complete”:所有数据已经准备好微软文档上说,在&script&元素的生命周期中,readyState
的这些取值不一定全部出现,但并没有指出哪些取值总会被用到。实践中,我们最感兴趣的是“loaded”和“complete”状态。Internet Explorer 对这两个 readyState
值所表示的最终状态并不一致,有时&script&元素会得到“loader”却从不出现“complete”,但另外一些情况下出现“complete”而用不到“loaded”。最安全的办法就是在 readystatechange 事件中检查这两种状态,并且当其中一种状态出现时,删除 readystatechange 事件句柄(保证事件不会被处理两次):清单 8 通过检查 readyState 状态加载 JavaScript 脚本var script = document.createElement("script")
script.type = "text/javascript";
//Internet Explorer
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange =
alert("Script loaded.");
script.src = "script1.js";
document.getElementsByTagName("head")[0].appendChild(script);大多数情况下,您希望调用一个函数就可以实现 JavaScript 文件的动态加载。下面的函数封装了标准实现和 IE 实现所需的功能:清单 9 通过函数进行封装function loadScript(url, callback){
var script = document.createElement ("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange =
callback();
} else { //Others
script.onload = function(){
callback();
script.src =
document.getElementsByTagName("head")[0].appendChild(script);
}此函数接收两个参数:JavaScript 文件的 URL,和一个当 JavaScript 接收完成时触发的回调函数。属性检查用于决定监视哪种事件。最后一步,设置 src 属性,并将&script&元素添加至页面。此 loadScript() 函数使用方法如下:清单 10 loadScript()函数使用方法loadScript("script1.js", function(){
alert("File is loaded!");
});您可以在页面中动态加载很多 JavaScript 文件,但要注意,浏览器不保证文件加载的顺序。所有主流浏览器之中,只有 Firefox 和 Opera 保证脚本按照您指定的顺序执行。其他浏览器将按照服务器返回它们的次序下载并运行不同的代码文件。您可以将下载操作串联在一起以保证他们的次序,如下:清单 11 通过 loadScript()函数加载多个 JavaScript 脚本loadScript("script1.js", function(){
loadScript("script2.js", function(){
loadScript("script3.js", function(){
alert("All files are loaded!");
});此代码等待 script1.js 可用之后才开始加载 script2.js,等 script2.js 可用之后才开始加载 script3.js。虽然此方法可行,但如果要下载和执行的文件很多,还是有些麻烦。如果多个文件的次序十分重要,更好的办法是将这些文件按照正确的次序连接成一个文件。独立文件可以一次性下载所有代码(由于这是异步进行的,使用一个大文件并没有什么损失)。动态脚本加载是非阻塞 JavaScript 下载中最常用的模式,因为它可以跨浏览器,而且简单易用。使用 XMLHttpRequest(XHR)对象此技术首先创建一个 XHR 对象,然后下载 JavaScript 文件,接着用一个动态 &script& 元素将 JavaScript 代码注入页面。清单 12 是一个简单的例子:清单 12 通过 XHR 对象加载 JavaScript 脚本var xhr = new XMLHttpRequest();
xhr.open("get", "script1.js", true);
xhr.onreadystatechange = function(){
if (xhr.readyState == 4){
if (xhr.status &= 200 && xhr.status & 300 || xhr.status == 304){
var script = document.createElement ("script");
script.type = "text/javascript";
script.text = xhr.responseT
document.body.appendChild(script);
xhr.send(null);此代码向服务器发送一个获取 script1.js 文件的 GET 请求。onreadystatechange 事件处理函数检查 readyState 是不是 4,然后检查 HTTP 状态码是不是有效(2XX 表示有效的回应,304 表示一个缓存响应)。如果收到了一个有效的响应,那么就创建一个新的&script&元素,将它的文本属性设置为从服务器接收到的 responseText 字符串。这样做实际上会创建一个带有内联代码的&script&元素。一旦新&script&元素被添加到文档,代码将被执行,并准备使用。这种方法的主要优点是,您可以下载不立即执行的 JavaScript 代码。由于代码返回在&script&标签之外(换句话说不受&script&标签约束),它下载后不会自动执行,这使得您可以推迟执行,直到一切都准备好了。另一个优点是,同样的代码在所有现代浏览器中都不会引发异常。此方法最主要的限制是:JavaScript 文件必须与页面放置在同一个域内,不能从 CDN 下载(CDN 指"内容投递网络(Content Delivery Network)",所以大型网页通常不采用 XHR 脚本注入技术。总结减少 JavaScript 对性能的影响有以下几种方法:
将所有的&script&标签放到页面底部,也就是&/body&闭合标签之前,这能确保在脚本执行前页面已经完成了渲染。
尽可能地合并脚本。页面中的&script&标签越少,加载也就越快,响应也越迅速。无论是外链脚本还是内嵌脚本都是如此。
采用无阻塞下载 JavaScript 脚本的方法:
使用&script&标签的 defer 属性(仅适用于 IE 和 Firefox 3.5 以上版本);
使用动态创建的&script&元素来下载并执行代码;
使用 XHR 对象下载 JavaScript 代码并注入页面中。通过以上策略,可以在很大程度上提高那些需要使用大量 JavaScript 的 Web 网站和应用的实际性能。
Steve Sounders 撰写的介绍了网站性能问题的现状、产生的原因,以及改善或解决性能问题的原则、技术技巧和最佳实践。
Steve Sounders 撰写的提供了提升网站性能的最佳实践和实用建议。
参考了在 JavaScript 影响页面下载性能方面的研究成果。
Steve Sounders 的个人博客 (developerWorks,2011 年 8 月):找出瓶颈,加快客户端内容的速度。 (developerWorks,2010 年 2 月):浏览器端页面渲染时间的性能分析。:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。:这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。,这是有关 Web 2.0 相关信息的一站式中心,包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。您还可以通过
栏目,迅速了解 Web 2.0 的相关概念。
查看 ,了解更多和 HTML5 相关的知识和动向。
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=http://www.ibm.com/developerworks/js/artrating/SITE_ID=10Zone=Web developmentArticleID=942924ArticleTitle=JavaScript 的性能优化:加载和执行publish-date=

我要回帖

更多关于 jsp页面引入js文件 的文章

 

随机推荐