JS在浏览器上的性能分析(一)脚本的下载与运行
来源:互联网 发布:电脑如何激活windows 编辑:程序博客网 时间:2024/05/23 18:54
JS在浏览器上的性能分析(一)脚本的下载与运行
前言
JS在浏览器上的性能,可以认为是开发者所面临的最严重的可用性问题。JS的阻塞特性使得浏览器在执行JS代码时不能同时做其他任何事情,而大多数浏览器使用单一的进程来处理用户界面(UI)刷新和JS脚本执行,所以同一时刻只能做一件事,JS执行过程耗时越久,浏览器所等待的响应时间越长。在这篇文章中,你将会学到浏览器脚本文件下载和执行的阻塞特性和如何对其进行优化。使用script元素的属性以及一些常用手段使脚本无阻塞加载。本篇文章参考了《高性能javascript》及《javascript模式》里的内容。
默认阻塞的脚本
script标签
script标签每次出现都会霸道的让页面等待脚本的解析和执行,同样,当使用script的src属性加载页面时,浏览器必须先花时间下载外链文件中的代码,然后解析并执行。在这个过程中,页面渲染和用户交互是完全被阻塞的。
浏览器之所以产生这样的行为,是因为当前HTML页面无从知晓JS的动作:JS可能会向document里添加内容、引入其它元素、甚至关闭标签。
所以浏览器会先(下载和)执行JS代码,然后才解析和渲染页面。
请看下面的代码:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title></head><body>hello world<script> while (1){}</script><div style="width: 300px;height: 50px;border: 1px solid red"></div></body></html>
不要妄想页面会输出hello world,然后由于循环而“卡壳”。事实上页面不会输出任何东西,因为脚本的执行一直占有浏览器进程,使得界面无法渲染。
优化
想要使页面得到更快的渲染,一是优化脚本的执行速度,例如使用观察者模式减少初始化代码的执行数量,这并不在这篇文章的阐述范围之内。请牢记,默认状态下,所有的脚本必须被执行后,页面才会开始渲染。即在浏览器解析页面之前,须先读取并执行脚本。我们现在试着对脚本的下载过程进行优化。
现代浏览器都允许并行下载JS文件,但JS文件的下载过程仍然会阻塞其他比如图片资源的下载。尽管JS文件的下载并不会相互影响,但是浏览器会等待全部的JS代码下载完成才执行之。
优化的关键在于使各种资源的下载并行执行,下面是分条列项的几点注意事项:
1. 雅虎特别性能小组提出的优化JS的首要规则:将脚本放在底部
这样做可以防止脚本代码的下载与执行阻塞页面其它资源,比如图片的下载(下载往往需要更多的时间),以尽量减少对整个页面下载的影响。
如果把脚本文件放在头部,那么需要等到所有脚本下载并执行完毕后才能下载图片等其他资源,这是多么的可怕啊。但如果我们把脚本放在body标签的尾部,则可以是其它资源的下载和脚本的下载与执行并发进行,能够大大加快页面的下载速度。
2. 减少script标签的数量,减少延时
3. 不要把内嵌脚本紧跟在link标签后面
<link ref="test.css" rel="stylesheet"> <script> // do something </script>
这样做会导致页面阻塞去等待样式表的下载,因为需要确保内嵌脚本在执行时能获得最准确的样式信息。
4. 减少外链脚本文件的数量——将多个外链JS文件合并成一个以减少HTTP开销
无阻塞的脚本
无阻塞脚本意味着脚本的下载和执行不阻塞其他资源的下载和页面的解析
script属性
可以通过设置script标签的defer和async属性使其拥有不阻塞的特性,它们仅对外部链接的script有效。
带有async或者defer的script都会立刻下载并不阻塞页面解析,它们的不同之处在于script执行的时机。
defer
<script src="test.js" defer></script>
会确保按脚本在页面中出现的顺序来执行,它们执行的时机是在页面解析完后, DOMContentLoaded事件之前,这时脚本可以获得页面的所有元素。如下事例代码:
html:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title> <script src="test.js" defer></script> <script src="test2.js" defer></script></head><body><div id='test' style="width: 300px;height: 50px;border: 1px solid red">hello world</div><script> alert('阻塞加载的script');</script><script> window.onload =function () { alert('页面加载完毕'); };</script></body></html>
test1.js
var div = document.getElementById('test');alert(div.innerHTML);
test2.js
alert('我是test2.js');
依次输出:
加载阻塞的javascripthello world我是test2.js页面加载完毕
async
async是html5中的新属性。带有async的script,一旦下载完成就开始执行(当然是在window的onload之前)。这意味着这些script 可能不会按它们出现在页面中的顺序来执行,如果你的脚本互相依赖并和执行顺序相关,就有很大的可能出问题。由于这依赖于下载文件的大小,我就不进行测试了。
动态脚本元素
类似于JSONP的形式,动态创建脚本元素并加载到页面中。这种技术的重点在于该元素被添加到页面时开始下载,文件的下载和执行过程不会阻塞页面其它进程。
<script> var script = document.createElement('script'); script.src = 'test2.js'; document.getElementsByTagName('head')[0].appendChild(script);</script>
但值得注意的有两点:
1. 把新创建的script标签添加到head标签里可以防止“操作已终止错误”
2. 下载完成后,返回的代码会立即执行,所以你需要通过onload事件控制加载顺序和依赖关系
script.onload = function () {}
XMLHttpRequest也是一种办法,但因为它无法实现跨域,不能从CDN上获取文件,因此不常使用。而像CSS等文件,已经是并行下载,不会阻塞页面其它进程,故没有必要动态加载CSS文件。
小结
虽然无阻塞脚本技术可以动态加载很多文件,但为了减小HTTP的开销,还是需要尽量减少文件数。
- JS在浏览器上的性能分析(一)脚本的下载与运行
- 运行在浏览器上的操作系统
- 片段一:生成供浏览器执行的JS脚本片段
- 关于applet小程序在浏览器上运行的备注
- 在eclipse模拟器上运行下载好的apk程序与删除
- 写能运行在IE和Firefox上的脚本
- 在linux的Apache上运行python脚本
- python脚本在linux上运行的两种方式
- 在secureCRT软件上运行一些简单的python脚本
- 分析浏览器的时间性能
- 基于linux服务器的性能分析与优化(一)
- 「微信小程序」剖析(二):框架原理 | 在桌面浏览器上运行的
- 让Caffe生成的数据集能在Theano上直接运行(一)——lmdb与protobuf
- 病毒木马查杀实战第025篇:JS下载者脚本木马的分析与防御
- 在终端上运行node.js的三种方式
- 浏览器js脚本和asp js脚本的共享使用
- 在EeePC上运行Android!(转)(也是代码下载配置编译的流程!)
- windows CE5.0模拟器 可在PC上运行的WINDOWS CE5.0下载(转载)
- 在商品展示页显示货币切换
- [题解]bzoj2002(HNOI2010)Bounce 弹飞绵羊
- springmvc MyBatis 调用Oracle存储过程,使用Map传递参数
- sql server
- Trafodion 存储过程的优势
- JS在浏览器上的性能分析(一)脚本的下载与运行
- Html和CSS基础
- VIM高频使用快捷键及命令
- POJ-1365 Prime Land (数论)
- OS超全开源框架、项目和学习资料汇总--数据库、缓存处理、图像浏览、摄像照相视频音频篇
- 亚马逊跨界女性内衣市场能靠谱么?
- jdk、jre
- 梁定郊推行贿赠之关键六个字
- MyEclipse2016下载