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


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模板引擎介绍
Feb 28 Javascript
动态加载jQuery的两种方法实例分析
Jul 17 Javascript
JS实现下拉菜单赋值到文本框的方法
Aug 18 Javascript
JS实现网页顶部向下滑出的全国城市切换导航效果
Aug 22 Javascript
浅析Javascript中bind()方法的使用与实现
May 30 Javascript
jQuery图片左右滚动代码 有左右按钮实例
Jun 20 Javascript
jquery Ajax实现Select动态添加数据
Jun 08 jQuery
详解用vue编写弹出框组件
Jul 04 Javascript
jQuery制作全屏宽度固定高度轮播图(实例讲解)
Jul 08 jQuery
总结js函数相关知识点
Feb 27 Javascript
vue获取验证码倒计时组件
Aug 26 Javascript
jQuery实现计算器功能
Oct 19 jQuery
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制作图型计数器的例子
2006/10/09 PHP
基于PHP的cURL快速入门教程 (小偷采集程序)
2011/06/02 PHP
php去掉文件前几行的方法
2015/07/29 PHP
一段实用的php验证码函数
2016/05/19 PHP
总结PHP内存释放以及垃圾回收
2018/03/29 PHP
Avengerls vs KG BO3 第三场2.18
2021/03/10 DOTA
Prototype源码浅析 Number部分
2012/01/16 Javascript
jQuery选择id属性带有点符号元素的方法
2015/03/17 Javascript
jQuery网页版打砖块小游戏源码分享
2015/08/20 Javascript
jQuery实现的分子运动小球碰撞效果
2016/01/27 Javascript
AngularJS学习笔记之依赖注入详解
2016/05/16 Javascript
AngularJS入门教程之 XMLHttpRequest实例讲解
2016/07/27 Javascript
JQuery统计input和textarea文字输入数量(代码分享)
2016/12/29 Javascript
解决vue+webpack打包路径的问题
2018/03/06 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
2018/05/18 Javascript
node.js学习笔记之koa框架和简单爬虫练习
2018/12/13 Javascript
vue.js中ref和$refs的使用及示例讲解
2019/08/14 Javascript
微信小程序后端无法保持session的原因及解决办法问题
2020/03/20 Javascript
python实现的简单FTP上传下载文件实例
2015/06/30 Python
Django原生sql也能使用Paginator分页的示例代码
2017/11/15 Python
python高阶爬虫实战分析
2018/07/29 Python
OpenCV+python手势识别框架和实例讲解
2018/08/03 Python
Python连接Impala实现步骤解析
2020/08/04 Python
Web时代变迁及html5与html4的区别
2016/01/06 HTML / CSS
11月升旗仪式讲话稿
2014/02/15 职场文书
出国留学计划书
2014/04/27 职场文书
竞聘上岗演讲
2014/05/19 职场文书
优秀毕业生求职信
2014/06/05 职场文书
企业承诺书格式范文
2015/04/28 职场文书
繁星春水读书笔记
2015/06/30 职场文书
2015年秋季小学开学典礼主持词
2015/07/16 职场文书
市级三好生竞选稿
2015/11/21 职场文书
MySql新手入门的基本操作汇总
2021/05/13 MySQL
美元符号 $
2022/02/17 杂记
Kubernetes中Deployment的升级与回滚
2022/04/01 Servers
联想win10摄像头打不开怎么办?win10笔记本摄像头打不开解决办法
2022/04/08 数码科技