其他分享
首页 > 其他分享> > 先从文件的下载和解析时机开始聊起

先从文件的下载和解析时机开始聊起

作者:互联网

03 先从文件的下载和解析时机开始聊起

本文的图,建议重新打开链接放大看

那么从什么时候开始呢?

  1. 从URL输入地址开始,浏览器的主进程调度其它进程开始服务
  2. DNS解析域名,找到服务器地址,和服务器建立TCP连接
  3. 发送一个GET网络请求,根据URL(统一资源符)描述,返回相应报文和资源
  4. 浏览器获取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 Tree);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、脚本和样式表的顺序

前面说过浏览器是有能力边资源下载和边解析,并且资源下载可以多线程并行下载,但是为什么会有阻塞现象呢?

先来了解一些相对权威的东西

HTML解析的时候,允许CSS资源并行下载(如果是链接的话,因为CSS的执行(即Parse)对DOM的解析并没有影响),但是对JS却不同(JavaScript能够对DOM节点进行操作,会影响DOM Tree的构建),具体请况如下

PS:注意 本文作者认为JS只阻塞比JS后下载的资源下载(即在js外联后面的链接资源,一定要等到JavaScript下载完成,才能完成下载)

(3) 整理一下 (1)(2)(3)

刚才1的时候说过了,要走一遍Parse HTML,接下来我们要做的事情就是这个。

前提知识点:1. style标签的样式和link外联的样式是一个级别的(从浏览器对样式的处理可以看的出来,内嵌的样式会被解析为DOM Tree的一部分);2. 资源解析默认不会和资源下载冲突,因为是两个进程的东西; 3. 以下会涉及一些Chrome Devtools 的performance的一些名词,如果你还没有怎么了解它,我不推荐以看下面的文章。

PS:有一个很变态,但是有意思的事情,下面一段代码

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Document</title>
  <!-- bg.jpg很大,index.js很小,但是JavaScript执行时间很长 -->
    <img src="./bg.jpg" alt=""> 
    <script src="./index.js"></script>
    <link rel="stylesheet" href="./global.css">
</head>
<body>
</body>
</html>

上面情况,img标签放在script上面,如果是“美好的情况”,图片下载图片的,js执行js的,互不干扰,但是JS在执行过程中,一直无法将img下载完成,直到js结束,它才有下载完成的趋势。但是有趣的是,这对网页来说视乎并没有影响,因为js线程一直阻塞了GUI线程,HTML还未解析完成,用户本来就看不见页面。还有一点值得注意的就是,IMG在等待下载完成,并轮到它解析的时候,会进行一次Parse HTML,解析的是该img标签,并在之后执行一些js的文档状态变化回调函数。

引用一段话:需要着重指出的是,这是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收和处理来自网络的其余内容的同时,呈现引擎会将部分内容解析并显示出来

这句话,一般发生

  1. 在网络资源都还在下载中,而HTML早就已经解析完成,这个时候浏览器直接进行布局,绘制,展示操作,不会等待资源下载才进行。当资源下载完成时,专门对资源处理解析,在对DOM Tree和CSSOM进行更新,在进行一次之后一系列的操作。

  2. 当HTML太大,如果有一个10000行代码的html,它会在解析大约3500行,强制停止HTML的解析,但是不会跳过Parse CSS,最后进行layout,多次循环处理,进行多轮的Parse HTML

三、能解决什么问题?

(1) 什么时候HTML成功被渲染出现了

HTML要在GPU渲染之后,才会展示,但是你可能会说那HTML都没解析完,如果里面有JS,为什么能访问DOM?
首先:上面说过,我认为JS能访问的DOM是DOM Tree,所以只要DOM Tree的对于节点已经被解析,就能被JS访问,HTML的解析就是从上到下,所以JS刚好能访问在其之前的所有元素。

(2) readstatuschange、load、DOMContentLoaded

readystate: interactive
DOMContentLoaded DOM Tree建立完成(HTML完全被加载并解析)
readystate: complete
load 所有资源加载完成包括样式、图片
事件执行顺序

(3) 一个! tab键生成的HTML渲染发生事件

上面有一个存疑的是
domLoading和domComplete,说的真的是DOM Tree建立吗?
我的回答:不是的,domComplete建立完成之前发生了attachment,说明是Render Tree树建立,而紧接触发readystatechange,所有我认为
domComplete指的是DOM Tree和CSSOM都建立好的情况,这种情况下,dom又和JS的documennt似乎一致,或许说domLoading就是完成document的建立。

(4) defer,async脚本下载和执行时机

  1. defer下载不会阻塞其它资源解析,直到下载完成也不会立即执行,等到文档被完全解析和显示,再执行。defer会按照原来在HTML中的顺序执行
  2. async 下载不会阻塞其它资源解析,一旦下载完成立即执行。async不会按照HTML的解析他们的顺序执行

四、附件证明

打开Chrome无痕模式,打开f12,进入performancetab页,进行reload

(1) HTML需要全部下载完成,才开始解析吗?

https://www.taobao.com 进入淘宝网,进行性能分析

标签:DOM,聊起,Tree,从文件,HTML,CSS,解析,下载
来源: https://blog.csdn.net/wucan111/article/details/110432682