浏览器渲染之布局阶段

·  阅读 77

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

布局阶段

现在,我们有 DOM 树和 DOM 树中元素的样式,但这还不足以显示页面,因为我们还不知道 DOM 元素的几何位置信息。那么接下来就需要计算出 DOM 树中可见元素的几何位置,我们把这个计算过程叫做布局。

Chrome 在布局阶段需要完成两个任务:创建布局树和布局计算。

我们开发者在开发时 布局 指的是: 对页面中的元素进行布局,包括流式布局 , 浮动布局 , flex布局 , Gride网格化布局等 布局使得页面中的元素盒子按照我们设计的样式进行部署。

而chrom会将我们开发的内容进行在浏览器中布局。

现在都是layoutTree了,

1. 创建布局树

你可能注意到了 DOM 树还含有很多不可见的元素,比如 head 标签,还有使用了 display:none 属性的元素。所以在显示之前,我们还要额外地构建一棵只包含可见元素布局树。

我们结合下图来看看布局树的构造过程:

img

从上图可以看出,DOM 树中所有不可见的节点都没有包含到布局树中。为了构建布局树,浏览器大体上完成了下面这些工作:

  • 遍历 DOM 树中的所有可见节点,并把这些节点加到布局树中;
  • 而不可见的节点会被布局树忽略掉,如 head 标签下面的全部内容,再比如 body.p.span 这个元素,因为它的属性包含 dispaly:none,所以这个元素也没有被包进布局树。

2. 布局计算

现在我们有了一棵完整的布局树。那么接下来,就要计算布局树节点的坐标位置了。布局的计算过程非常复杂,我们这里先跳过不讲。

在执行布局操作的时候,会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫 LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单

QA:QA: css文件被阻塞了,会阻止DOM树的合成吗?会阻塞页面的显示吗?

CSS 加载不会阻塞 DOM 树解析,但会阻塞 DOM 树渲染。 所以为了避免用户看到长时间的白屏,应该尽快提高 CSS 的加载速度。 1.使用CDN; 2.CSS的压缩(使用webpack、gulp等打包工具); 3、合理使用缓存(设置缓存控制、表达式和e-tag); DOM解析和CSS解析是两个并行的过程,所以这也解释了为什么CSS加载不会阻塞DOM解析。 但是因为render tree依赖于DOM树和cssom树,所以必须等到cssom树构建完成,也就是CSS资源加载完成。

当从服务器接收HTML页面的第一批数据时,DOM解析器就开始工作了,在解析过程中,如果遇到了JS脚本,如下所示:

<html>
    <body>
         geek
        <script>
        document.write("--foo")
        </script>
    </body>
</html>
复制代码

那么DOM解析器会先执行JavaScript脚本,执行完成之后,再继续往下解析。

那么第二种情况复杂点了,我们内联的脚本替换成js外部文件,如下所示:

<html>
    <body>
        geek
        <script type="text/javascript" src="foo.js"></script>
 </body>
</html>
复制代码

这种情况下,当解析到JavaScript的时候,会先暂停DOM解析,并下载foo.js文件,下载完成之后执行该段JS文件,然后再继续往下解析DOM。这就是JavaScript文件为什么会阻塞DOM渲染。

总结: 真正的页面渲染需要css,html完全加载并解析完毕生成布局树然后布局计算然后绘制到页面上,但是js的特殊性,js会阻塞dom解析,从而阻止了页面渲染。 css的加载和解析和html的加载和解析是并行的。 而且通过实验可以发现js的执行,需要等待css加载完成。可能是因为引擎没法判断你是否在脚本里访问了元素的样式,所以只要出现脚本,全部阻塞处理

我觉得只能说css会间接通过阻塞js的执行来阻塞dom树的构建,当只有css和html文档时css不会阻塞dom树的构建。

分类:
前端
标签: