03 先从文件的下载和解析时机开始聊起
本文的图,建议重新打开链接放大看
那么从什么时候开始呢?
- 从URL输入地址开始,浏览器的主进程调度其它进程开始服务
- DNS解析域名,找到服务器地址,和服务器建立TCP连接
- 发送一个GET网络请求,根据URL(统一资源符)描述,返回相应报文和资源
- 浏览器获取HTML资源,开始解析…。
这里就涉及到一个问题:浏览器一定要等到HTML全部下载完毕,才开始解析吗?
我的答案:是的,它表现的行为是这样的,也应该这么做。
如何证明:你无论去那个网站去看,无论多慢,或者多快,一直要等到HTML的请求完成,资源下载并加载完成,才会开始解析
具体请看证明1
一、解析开始
(1) 解析什么
下载HTML文件,直到下载完成才能进行第二步 => 解析HTML (Parse HTML)。HTML、JavaScript和CSS中,除了CSS,没有文件可以边被下载件,然后边被解析,但是这并不意味这,当前文件在解析时,不能下载其它资源(这就涉及到资源的并发下载)。
PS:浏览器的渲染进程的GUI线程在解析HTML。网络资源的下载是浏览器的主进程在执行,所以它有能力同时解析资源和下载其它资源(理想状态下)。
(2) 在Parse Html的大致过程
GUI线程,先解析html(HTML Parser)构建DOM树(DOM Tree),注意解析完DOM树;再解析CSS(CSS Parser )构建CSS对象模型(CSSOM <=> CSS Object Model);DOM树和CSS对象模型进行连接(attachment),生成渲染树(Render Tree);进行回流(根据Render Tree 计算他们在设备视口的确切位置和大小,也叫 Layout );进行重绘(拿到回流之后的呈现树,得到节点的绝对像素,主要是视觉上的效果,注意只是计算了像素,还未渲染展示,它也叫Painting);最后,Display 将像素发送给GPU,展示在也页面上。
PS:这个Display操作,是交付给GPU的,涉及GPU的是浏览器进程 即 GPU进程,因此 GUI线程的Parse HTML 和渲染进程的Display可以并行!这意味着浏览器是可以边进行GUI线程的解析,边进行GPU的Display工作。
关于上面的过程还是有很多细节可以扣:
上面的操作真的是所有的情况吗?那我们来自己走一遍Parse HTML,但是在这之前,我们还需要一些基本认识
=> 文件下载及其解析的时机!
(3) 处理HTML、脚本和样式表的顺序
前面说过浏览器是有能力边资源下载和边解析,并且资源下载可以多线程并行下载,但是为什么会有阻塞现象呢?
先来了解一些相对权威的东西
-
第一点:脚本
网络的模型是同步的。解析器遇到 <script> 标记时立即解析并执行脚本。文档的解析将停止,直到脚本执行完毕,如果脚本是外部的,那么解析过程会停止,直到从网络同步抓取资源完成后再继续,此模型已经使用了多年,也在 HTML4 和 HTML5 规范中进行了指定。作者也可以将脚本标注为“defer”,这样它就不会停止文档解析,而是等到解析结束才执行。HTML5 增加了一个选项,可将脚本标记为异步,以便由其他线程解析和执行PS:补充说明 JavaScript 的性能优化:加载和执行
我们可以发现一个有趣的现象:第一个 JavaScript 文件开始下载,与此同时阻塞了页面其他文件的下载。此外,从 script1.js 下载完成到 script2.js 开始下载前存在一个延时,这段时间正好是