浏览器加载、渲染和解析过程黑箱简析


Posted in Javascript onNovember 29, 2012

用 Fiddler 监控,在 IE6 下,资源下载顺序为:
浏览器加载、渲染和解析过程黑箱简析

很明显,下载顺序从上到下,文档流中先出现的资源先下载。在 IE8, Safari, Chrome 等浏览器下也类似。

Firefox 对下载顺序做了优化
浏览器加载、渲染和解析过程黑箱简析
Firefox 会将 js, css 提前下载,而将图片等资源延迟到后面下载。

对于渲染,利用 Fiddler 将网速调慢,可以看到 css 下载后会马上渲染到页面,渲染和下载同步进行。js 的解析和运行,也类似。

对于 js 运行,以及页面加载相关事件的触发,特别做了测试。在 Firefox 下,打开测试页面:

[22:13:32.947] HTML Start[22:13:32.947] normal inline script run time[22:13:34.904] normal external script run time[22:13:35.775] [body] normal external script run time[22:13:35.789] [body end] normal external script run time[22:13:35.789] HTML End[22:13:35.791] deferred inline script run time[22:13:35.791] deferred external script run time[22:13:35.793] DOMContentLoaded[22:13:38.144] images[0] onload[22:13:38.328] images[1] onload[22:13:39.105] images[2] onload[22:13:39.105] images[3] onload[22:13:39.106] window.onload

很明显,JS 的运行严格按照文档流中的顺序进行。其中 deferred 的脚本会在最后运行(注:Firefox 3.5 开始支持 defer,而且支持得很完美)。

再来看下 IE8,结果如下:

[22:33:56.806] HTML Start[22:33:56.826] normal inline script run time[22:33:57.786] normal external script run time[22:33:57.812] deferred inline script run time[22:33:57.816] document.readyState = interactive[22:33:57.934] [body] normal external script run time[22:33:58.310] [body end] normal external script run time[22:33:58.310] HTML End[22:33:58.346] deferred external script run time[22:33:58.346] images[0].readyState = loading[22:33:58.346] images[0].readyState = complete[22:33:58.346] images[0] onload[22:33:58.361] doScroll[22:33:58.451] images[1].readyState = loading[22:33:58.479] images[1].readyState = complete[22:33:58.479] images[1] onload[22:33:58.794] images[2].readyState = loading[22:33:58.854] images[2].readyState = complete[22:33:58.854] images[2] onload[22:33:58.876] images[3].readyState = loading[22:33:58.876] images[3].readyState = complete[22:33:58.876] images[3] onload[22:33:58.887] document.readyState = complete[22:33:58.888] window.onload

可以看出,IE8 下,defer 只对 external 脚本有效,对 inline 脚本无效。另,与 DOMContentLoaded 最接近的是 doScroll. 这是 doScroll 被广泛用来模拟 DOMContentLoaded 的原因。小心:仅仅是模拟,细节上并不等价。

还可以得到一个有点意外的结果:放在 body 结束前的脚本,执行时,依旧最好放在 domready 事件中。无论在 Firefox 还是 IE 下,解析到 HTML End 时,并不代表 DOM 可以安全操作,特别是页面比较复杂时。

从上面数据中,也可以看出 YSlow 性能优化法则里,建议将样式置顶和脚本置底的根据。

有兴趣的可以进一步测试动态添加样式和脚本的情形,会稍有不同,但没有特别 surprise.

最后总结下

页面资源的下载顺序是从上到下的,文档流中先出现的资源先下载(注:存在并发,具体请参考 UA Profiler)。当某一样式下载完成时,会立刻渲染到页面(体现了层叠样式表中层叠在渲染时的含义)。当某一脚本下载完成时,也会立刻解析和运行。脚本的运行严格按照文档流中的顺序进行,deferred 的脚本会在正常脚本运行之后运行(Firefox 和 IE 下)。

特别需要留意:脚本运行时,会暂停该脚本之下所有资源的下载(因为脚本可能改变文档流,甚至跳转页面,浏览器的暂停策略是合理的)。要小心内联脚本,经常会阻塞后续下载。

好了,废话不多说。以上结果,建议各位亲自测试,反复测试,疯狂测试,一直到眼花缭乱稀里糊涂恍然大悟继续糊涂为止……

Javascript 相关文章推荐
Javascript 二维数组
Nov 26 Javascript
JS实现仿新浪微博发布内容为空时提示功能代码
Aug 19 Javascript
WEB前端开发都应知道的jquery小技巧及jquery三个简写
Nov 15 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
Nov 23 Javascript
js+flash实现的5图变换效果广告代码(附演示与demo源码下载)
Apr 01 Javascript
终于实现了!精彩的jquery弹幕效果
Jul 18 Javascript
关于微信上网页图片点击全屏放大效果
Dec 19 Javascript
原生JS实现圣旨卷轴展开效果
Mar 06 Javascript
bootstrap响应式表格实例详解
May 15 Javascript
详解js跨域请求的两种方式,支持post请求
May 05 Javascript
浅谈Vue页面级缓存解决方案feb-alive(上)
Apr 14 Javascript
layui关闭层级、简单监听的实例
Sep 06 Javascript
javascript控制swfObject应用介绍
Nov 29 #Javascript
javascript 保存文件到本地实现方法
Nov 29 #Javascript
jquery连缀语法如何实现
Nov 29 #Javascript
javascript 使td内容不换行不撑开
Nov 29 #Javascript
json原理分析及实例介绍
Nov 29 #Javascript
javascript全局变量封装模块实现代码
Nov 28 #Javascript
Javascript Request获取请求参数如何实现
Nov 28 #Javascript
You might like
PHP之APC缓存详细介绍 apc模块安装
2014/01/13 PHP
PHPExcel简单读取excel文件示例
2016/05/26 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
Thinkphp5+Redis实现商品秒杀代码实例讲解
2020/12/29 PHP
遍历jquery对象的代码分享
2011/11/02 Javascript
JS跨域总结
2012/08/30 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
jquery实现滑动图片自己测试的例子
2013/11/05 Javascript
JS简单的图片放大缩小的两种方法
2013/11/11 Javascript
jquery鼠标停止移动事件
2013/12/21 Javascript
一款基于jQuery的图片场景标注提示弹窗特效
2015/01/05 Javascript
JS替换字符串中空格方法
2015/04/17 Javascript
js如何打印object对象
2015/10/16 Javascript
浅谈javascript中的call、apply、bind
2016/03/06 Javascript
js原型链与继承解析(初体验)
2016/05/09 Javascript
JS组件Bootstrap实现图片轮播效果
2016/05/16 Javascript
jQuery EasyUi 验证功能实例解析
2017/01/06 Javascript
浅谈angular4生命周期钩子
2017/09/05 Javascript
微信小程序的开发范式BeautyWe.js入门详解
2019/07/10 Javascript
快速解决layui弹窗按enter键不停弹窗的问题
2019/09/18 Javascript
jQuery+ThinkPHP实现图片上传
2020/07/23 jQuery
解决vue-router 嵌套路由没反应的问题
2020/09/22 Javascript
pyqt4教程之widget使用示例分享
2014/03/07 Python
Django框架教程之正则表达式URL误区详解
2018/01/28 Python
python 获取utc时间转化为本地时间的方法
2018/12/31 Python
pycharm的python_stubs问题
2020/04/08 Python
Python+pyftpdlib实现局域网文件互传
2020/08/24 Python
利用CSS3 动画 绘画 圆形动态时钟
2018/03/20 HTML / CSS
canvas实现漂亮的下雨效果的示例
2018/04/18 HTML / CSS
创造美妙香氛体验:Aera扩散器和香水
2018/11/25 全球购物
银行求职信
2014/05/31 职场文书
运动会广播稿100字
2015/08/19 职场文书
大学生志愿者心得体会
2016/01/15 职场文书
如何书写邀请函?
2019/06/24 职场文书
如何利用pygame实现打飞机小游戏
2021/05/30 Python
Oracle数据库中通用的函数实例详解
2022/03/25 Oracle