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


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监听浏览器的问题
Jun 23 Javascript
JavaScript中几种常见排序算法小结
Feb 22 Javascript
DOM节点的替换或修改函数replaceChild()用法实例
Jan 12 Javascript
JavaScript使用shift方法移除素组第一个元素实例分析
Apr 06 Javascript
详解js中call与apply关键字的作用
Nov 21 Javascript
js 文字超出长度用省略号代替,鼠标悬停并以悬浮框显示实例
Dec 06 Javascript
微信小程序自定义组件封装及父子间组件传值的方法
Aug 28 Javascript
简述vue状态管理模式之vuex
Aug 29 Javascript
原生js基于canvas实现一个简单的前端截图工具代码实例
Sep 10 Javascript
这15个Vue指令,让你的项目开发爽到爆
Oct 11 Javascript
js实现tab栏切换效果
Aug 02 Javascript
使用Canvas绘制一个游戏人物属性图
Mar 25 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异常:Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE  eval()'d code error
2011/05/19 PHP
深入PHP许愿墙模块功能分析
2013/06/25 PHP
php中preg_match的isU代表什么意思
2015/10/01 PHP
php组合排序简单实现方法
2016/10/15 PHP
thinkphp关于简单的权限判定方法
2017/04/03 PHP
PHP PDOStatement::columnCount讲解
2019/01/30 PHP
javascript中数组中求最大值示例代码
2013/12/18 Javascript
JavaScript对象参数的引用传递
2016/01/14 Javascript
分享网页检测摇一摇实例代码
2016/01/14 Javascript
jQuery遍历json的方法分析
2016/04/16 Javascript
JS模仿手机端九宫格登录功能实现代码
2016/04/28 Javascript
JS清除字符串中重复值的实现方法
2016/08/03 Javascript
vue多级多选菜单组件开发
2020/09/08 Javascript
Angular2 Service实现简单音乐播放器服务
2017/02/24 Javascript
配置nodejs环境的方法
2017/05/13 NodeJs
深入浅析Node.js单线程模型
2017/07/10 Javascript
使用vue官方提供的模板vue-cli搭建一个helloWorld案例分析
2018/01/16 Javascript
es6中let和const的使用方法详解
2020/02/24 Javascript
JS+Canvas实现五子棋游戏
2020/08/26 Javascript
仿照Element-ui实现一个简易的$message方法
2020/09/14 Javascript
vant中的toast轻提示实现代码
2020/11/04 Javascript
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
Django 对象关系映射(ORM)源码详解
2019/08/06 Python
win10系统Anaconda和Pycharm的Tensorflow2.0之CPU和GPU版本安装教程
2019/12/03 Python
python等待10秒执行下一命令的方法
2020/07/19 Python
如何基于Python按行合并两个txt
2020/11/03 Python
法国综合购物网站:RueDuCommerce
2016/09/12 全球购物
网络体系结构及协议的定义
2014/03/13 面试题
高级护理专业毕业生推荐信
2013/12/25 职场文书
办公室文员工作职责
2014/01/31 职场文书
2014年学习雷锋活动总结
2014/03/01 职场文书
个人评语大全
2014/05/04 职场文书
预备党员综合考察材料
2014/05/31 职场文书
党支部活动策划方案
2014/08/18 职场文书
二手车转让协议书
2015/01/29 职场文书
教师节主持词开场白
2015/05/29 职场文书