一个页面的呈现主要是由浏览器渲染进程实现的(render进程),主要做用为页面的渲染,脚本执行,事件处理等。而render进程是多线程的,它主要包含如下主要线程:javascript
1 GUI渲染线程css
2 JS引擎线程html
3 事件触发线程java
4 定时触发器线程node
5 异步http请求线程jquery
由上述GUI线程和JS引擎互斥的关系,咱们也就能更好的理解为何JS运行会阻塞页面的渲染,也就是常说的JS阻塞特性
。segmentfault
0.加载总体html文件浏览器
1.至上而下解析html 多线程
2.解析html创建dom树,遇到诸如<script>、<link>等标签时,就会去下载相应内容,并解
析、执行。若是是<link>标签,解析css构建CSSOM树app
4.DOM和CSSOM结合生成render树
5.布局render树(Layout/reflow),负责各元素尺寸、位置的计算
6.绘制render树(paint),绘制页面像素信息
7.浏览器会将各层的信息发送给GPU,GPU会将各层合成(composite),显示在屏幕上。
HTML解析过程是至上而下的,当html解析器遇到诸如<script>、<link>等标签时,就会去下载相应内容。且加载、解析、执行JavaScript会阻止解析器往下执行,要强调 渲染
和 下载
是不冲突的,渲染是GUI线程在执行,下载是下载线程在执行,浏览器多线程。
如下为实验:
HTML代码:
<!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>浅谈Html页面内容执行顺序</title> <link rel="stylesheet" href="red.css"> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="test.js"></script> <link rel="stylesheet" href="font.css"> <script type="text/javascript" src="test2.js"></script> </head> <body> <p>html顺序测试</p> <img src="1.png" alt=""> <input value="101" /> <link rel="stylesheet" href="styl.css"> </body> </html>
Test.js代码:
for(var i=0;i<10000;i++){ console.log("delay"); if(i==9999){ loadStyle('lime.css'); } } function loadStyle(url){ var link = document.createElement('link'); link.type = 'text/css'; link.rel = 'stylesheet'; link.href = url; var head = document.getElementsByTagName('head')[0]; head.appendChild(link); }
Test2.js代码:
console.log("after blocking script,you will appear");
从图中能够看出:遇到<script>、<link>等标签时,就会下载相应的内容。
从下载
的角度讲:
总结
下就是:当HTML解析器遇到<script>、<link>、<img>标签,开始下载时,只存在一种阻塞状况,就是<script>标签会阻止<img>资源下载,其他<script>、<link>相互之间下载没有影响。下载完成以后,就会运行解析相应的JS文件或者CSS文件,运行JS文件须要JS引擎线程,前面提到,JS引擎和GUI时互斥的,因此在 解析
的角度讲,JS引擎运行,会阻塞GUI,即阻止页面渲染。从上图能够看出,在test.js下载以后,解析运行时,因为有for循环函数的运行,页面首次渲染时间被推至1100ms才渲染完成。
HTML代码
<!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <meta name="robots" content="noindex"> <title>Hang test</title> <style> body { font-family: sans-serif; } </style> <script> console.log('doc state: ' + document.readyState); document.onreadystatechange = function () { console.log('doc state change: ' + document.readyState); }; </script> <link href="http://hang.nodester.com/hang.css?5000" rel="stylesheet" /> </head> <body> <p>Refresh with the console open to see the hanging</p> <script src="http://static.jsbin.com/js/render/edit.js?4.1.4" async></script> <script>jsbinShowEdit && jsbinShowEdit({"static":"http://static.jsbin.com","root":"http://jsbin.com"});</script> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-1656750-34', 'auto'); ga('require', 'linkid', 'linkid.js'); ga('require', 'displayfeatures'); ga('send', 'pageview'); </script> </body> </html>
由https://blog.csdn.net/gbstack...,咱们能够获得:
由图中能够看出:
外部脚本与外部样式是并行加载
(即在 下载
阶段,<script>、<link>互不影响,符合上述结论),但直到外部样式加载完毕,外部脚本才开始执行(即外部样式的下载,虽然不会影响外部脚本的下载,但会影响脚本的运行)
文章参考:
https://segmentfault.com/a/11...
http://www.cnblogs.com/dojo-l...