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


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 相关文章推荐
基于逻辑运算的简单权限系统(实现) JS 版
Mar 24 Javascript
js FLASH幻灯片字符串中有连接符&的处理方法
Mar 01 Javascript
JQuery EasyUI 日期控件如何控制日期选择区间
May 05 Javascript
javascript判断数组内是否重复的方法
Apr 21 Javascript
chrome不支持form.submit的解决方案
Apr 28 Javascript
JS实现的表格行上下移动操作示例
Aug 03 Javascript
Sequelize中用group by进行分组聚合查询
Dec 12 Javascript
JavaScript生成.xls文件的代码
Dec 22 Javascript
js-FCC算法-No repeats please字符串的全排列(详解)
May 02 Javascript
详解使用mpvue开发github小程序总结
Jul 25 Javascript
JavaScript中常用的简洁高级技巧总结
Mar 10 Javascript
如何基于layui的laytpl实现数据绑定的示例代码
Apr 10 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 微信开发获取用户信息如何实现
2016/12/13 PHP
利用 fsockopen() 函数开放端口扫描器的实例
2017/08/19 PHP
浅谈laravel-admin form中的数据,在提交后,保存前,获取并进行编辑
2019/10/21 PHP
thinkphp 框架数据库切换实现方法分析
2020/05/18 PHP
推荐:极酷右键菜单
2006/11/29 Javascript
JQuery里选择超链接的实现代码
2011/05/22 Javascript
javascript的内存管理详解
2013/08/07 Javascript
JavaScript 语言基础知识点总结(思维导图)
2013/11/10 Javascript
jQuery实现仿百度帖吧头部固定导航效果
2015/08/07 Javascript
Nodejs中的this详解
2016/03/26 NodeJs
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
angular forEach方法遍历源码解读
2017/01/25 Javascript
jQuery插件HighCharts实现的2D对数饼图效果示例【附demo源码下载】
2017/03/09 Javascript
js中的触发事件对象event.srcElement与event.target详解
2017/03/15 Javascript
Vue中img的src属性绑定与static文件夹实例
2017/05/18 Javascript
使用jQuery.Pin垂直滚动时固定导航
2017/05/24 jQuery
VSCode配置react开发环境的步骤
2017/12/27 Javascript
Bootstrap table表格初始化表格数据的方法
2018/07/25 Javascript
atom-design(Vue.js移动端组件库)手势组件使用教程
2019/05/16 Javascript
如何用webpack4.0撸单页/多页脚手架 (jquery, react, vue, typescript)
2019/06/18 jQuery
vue的路由映射问题及解决方案
2019/10/14 Javascript
JS代码触发事件代码实例
2020/01/02 Javascript
Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例
2020/11/18 Vue.js
[37:47]IG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python开发游戏的前期准备
2019/05/05 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
python使用梯度下降和牛顿法寻找Rosenbrock函数最小值实例
2020/04/02 Python
利用python为PostgreSQL的表自动添加分区
2021/01/18 Python
canvas实现图片镜像翻转的2种方式
2020/07/22 HTML / CSS
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
教师自我评价范例
2013/09/24 职场文书
学校司机岗位职责
2013/11/14 职场文书
期中考试反思800字
2014/05/01 职场文书
公司承诺函范文
2015/01/21 职场文书
2015年煤矿安全工作总结
2015/05/23 职场文书
使用python创建股票的时间序列可视化分析
2022/03/03 Python