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


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 27 Javascript
javaScript 读取和设置文档元素的样式属性
Apr 14 Javascript
JavaScript词法作用域与调用对象深入理解
Nov 29 Javascript
全面解析bootstrap格子布局
May 22 Javascript
详解node中创建服务进程
May 09 Javascript
Node.JS中快速扫描端口并发现局域网内的Web服务器地址(80)
Sep 18 Javascript
深入浅析ES6 Class 中的 super 关键字
Oct 20 Javascript
详解javascript中的babel到底是什么
Jun 21 Javascript
axios实现文件上传并获取进度
Mar 25 Javascript
Vue快速实现通用表单验证的示例代码
Jan 09 Javascript
vue 通过绑定事件获取当前行的id操作
Jul 27 Javascript
浅谈vue-props的default写不写有什么区别
Aug 09 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模板之Phpbean的目录结构
2008/01/10 PHP
PHP网站备份程序代码分享
2011/06/10 PHP
php session_start()出错原因分析及解决方法
2013/10/28 PHP
PHP登录环节防止sql注入的方法浅析
2014/06/30 PHP
PHP中使用file_get_contents抓取网页中文乱码问题解决方法
2014/12/17 PHP
浅谈php常用的7大框架的优缺点
2020/07/20 PHP
js常用函数 不错
2006/09/08 Javascript
如何实现JS函数的重载
2006/09/22 Javascript
使用按钮控制以何种方式打开新窗口的属性介绍
2012/12/17 Javascript
如何改进javascript代码的性能
2015/04/02 Javascript
轻松学习jQuery插件EasyUI EasyUI实现拖动基本操作
2015/11/30 Javascript
基于jQuery Tipso插件实现消息提示框特效
2016/03/16 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
2016/10/28 Javascript
JavaScript正则表达式小结(test|match|search|replace|split|exec)
2016/12/08 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
Node.js Mongodb 密码特殊字符 @的解决方法
2017/04/11 Javascript
Js自定义多选框效果的实例代码
2017/07/05 Javascript
使用jquery模拟a标签的click事件无法实现跳转的解决
2018/12/04 jQuery
详解微信小程序网络请求接口封装实例
2019/05/02 Javascript
微信小程序调用天气接口并且渲染在页面过程详解
2019/06/24 Javascript
微信小程序在text文本实现多种字体样式
2019/11/08 Javascript
使用JS来动态操作css的几种方法
2019/12/18 Javascript
Vue是怎么渲染template内的标签内容的
2020/06/05 Javascript
python3 Scrapy爬虫框架ip代理配置的方法
2020/01/17 Python
python的reverse函数翻转结果为None的问题
2020/05/11 Python
如何解决flask修改静态资源后缓存文件不能及时更改问题
2020/08/02 Python
css3高级选择器使用方法
2013/12/02 HTML / CSS
使用HTML5原生对话框元素并轻松创建模态框组件
2019/03/06 HTML / CSS
美国婴儿用品店:Babies”R”Us
2017/10/12 全球购物
乔丹诺(Giordano)酒庄德国官网:找到最好的意大利葡萄酒
2017/12/28 全球购物
Public Desire美国/加拿大:全球性的在线鞋类品牌
2018/12/17 全球购物
总经理助理岗位职责
2013/11/08 职场文书
护理学专业推荐信
2013/12/03 职场文书
初中生期末评语大全
2014/04/24 职场文书
临床医学生职业规划书范文
2014/10/25 职场文书
2016高一新生军训心得体会
2016/01/11 职场文书