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


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 23 Javascript
sails框架的学习指南
Dec 22 Javascript
JavaScript中连接操作Oracle数据库实例
Apr 02 Javascript
javascript日期处理函数,性能优化批处理
Sep 06 Javascript
谈一谈javascript闭包
Jan 28 Javascript
JS实现添加,替换,删除节点元素的方法
Jun 30 Javascript
浅析BootStrap Treeview的简单使用
Oct 12 Javascript
jQuery Ajax前后端使用JSON进行交互示例
Mar 17 Javascript
JS滚动到指定位置导航栏固定顶部
Jul 03 Javascript
jQuery简介_动力节点Java学院整理
Jul 04 jQuery
在nuxt中使用路由重定向的实例
Nov 06 Javascript
vuex页面刷新导致数据丢失的解决方案
Dec 10 Vue.js
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
西德产收音机
2021/03/01 无线电
php文件怎么打开 如何执行php文件
2011/12/21 PHP
Linux系统下php获得系统分区信息的方法
2015/03/30 PHP
PHP统一页面编码避免乱码问题
2015/04/09 PHP
功能强大的PHP图片处理类(水印、透明度、旋转)
2015/10/21 PHP
微信公众号之主动给用户发送消息功能
2019/06/22 PHP
Javascript操纵Cookie实现购物车程序
2007/02/15 Javascript
Javascript面向对象设计一 工厂模式
2011/12/20 Javascript
js弹出窗口之弹出层的小例子
2013/06/17 Javascript
js动态移动滚动条至底部示例代码
2014/04/24 Javascript
jQuery中noconflict函数的实现原理分解
2015/02/03 Javascript
浅析javascript中的DOM
2015/03/01 Javascript
jQuery中dom元素上绑定的事件详解
2015/04/24 Javascript
关于数据与后端进行交流匹配(点亮星星)
2016/08/03 Javascript
Bootstrap的class样式小结
2016/12/01 Javascript
JS ES6多行字符串与连接字符串的表示方法
2017/04/26 Javascript
Nodejs之TCP服务端与客户端聊天程序详解
2017/07/07 NodeJs
laydate 显示结束时间不小于开始时间的实例
2017/08/11 Javascript
微信小程序实现下拉菜单切换效果
2020/03/30 Javascript
在antd4.0中Form使用initialValue操作
2020/11/02 Javascript
Vertx基于EventBus发送接受自定义对象
2020/11/16 Javascript
Js实现粘贴上传图片的原理及示例
2020/12/09 Javascript
[03:23]我的刀塔你不可能这么可爱 第一期金萌萌的故事
2014/06/20 DOTA
[01:05:56]2018DOTA2亚洲邀请赛3月29日 小组赛A组 Newbee VS VG
2018/03/30 DOTA
python原始套接字编程示例分享
2014/02/21 Python
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
python3实现字符串操作的实例代码
2019/04/16 Python
django 文件上传功能的相关实例代码(简单易懂)
2020/01/22 Python
Python3标准库之dbm UNIX键-值数据库问题
2020/03/24 Python
Python实现转换图片背景颜色代码
2020/04/30 Python
文明演讲稿范文
2014/05/12 职场文书
学习退步检讨书
2014/09/28 职场文书
离婚答辩状范文
2015/05/22 职场文书
离婚案件上诉状
2015/05/23 职场文书
python3使用diagrams绘制架构图的步骤
2021/04/08 Python
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript