浏览器页面是怎么渲染的
程序员文章站
2022-07-03 16:35:04
...
正如前面写的 浏览器中输入URL后会发生什么事情--超级详细版 中介绍的一样,一个 页面的渲染过程 也涉及到了 很多的东西,以及进程之间的通信
1、网络
- 网络进程接收到了 一个 html 文件 之后,除了会判断 content-type 之外,还会发生什么呢?
- 首先,要知道的是 TCP 的通讯 并不是一次性的,而是一个包一个包发过来的
- 网络进程也是如此,和 渲染进程建立了 通道之后,也是一个包一个包地发给渲染进程
2、渲染进程——解析
<head>
<style>
div{
font-size: 20px;
}
</style>
</head>
<body>
<div class="div1">div1</div>
<script>
document.querySelect('.div1').style.color = "red";
document.querySelect('.div2').style.color = "red";
</script>
<div class="div2">div2</div>
</body>
- 渲染进程 在接收到 文件之后,会将页面清空,这里就会出现一个白屏的 现象
- 渲染进程 开始 一点一点地 解析 数据包,然后生成 dom 树
- 在这个过程之中,如果遇到了 内嵌的 css 或者 link 标签上的 css 外链,那么 继续 解析 dom ,并行地下载 css 以及解析 cssom
- 那么 是不是 css 就不会阻止 dom 的解析呢?
- 答案是 否定的,关键点 就在 js 上
- 看上面的那一段代码,可以看到,js 是可以 读取 一个 dom 的 css 的,也就是 读取到 cssom 的
- 而众所周知的事情是,js 执行 的时候 是会 阻止 dom 继续解析的
- 所以 为了 读取到 一个 dom 的css ,这个时候的 js 会等 css 加载完,cssom 也创建完毕之后,才开始执行
- 这里的 css 就变相的 阻止了 dom 的解析
- 那么问题来了,js 会完成 对 div2 的修改吗?这个时候 的 dom 还没有执行到 div2,js 自然是 读取不到 div2 的
- 如果遇到 js 的外链呢?
- 这个问题就实在是 老生常谈了
- 还要分情况来讨论,如 defer (告诉浏览器我完全不会操作 dom,所以会 加载文件之后,等到 DOMContentLoaded 之前 顺序执行)和 async (加载的时候 不会阻断 dom,但是 加载完成之后立即执行,这里就有可能会 阻断 dom 解析,而且 多个 async 也不是 顺序执行的) 的情况
- 然后 就是 将 dom 树 和 cssom 树合并,对 靠近视口的 内容 拥有较高的优先级,进行光栅化,呈现到 用户面前
3、渲染进程——渲染
这里主要讨论一下 js 动画 和 css 动画
- 相信有很多人 知道 css 动画是比 js 动画 要快的,那么到底 为什么快呢?
- 这里有很多理由,比如 js 和 dom 树之间线程的 通信,js 动画导致的 回流与重绘
- 讲 css 动画,要了解一个概念,那就是图层 layers
- 在浏览器 的一张 图片中,页面 其实是可以进行分层的
- 而进行了 分层的 图层 就摆脱了 全局的 回流与重绘的过程,只会 顾着自己的一亩三分地。在内容改变之后,只会 和之前的图片 一重叠,新的 页面就这样 出来了
- 其次,在 js 和 渲染线程之外,浏览器 又开了 一个新的 线程,那就是合成 线程,在这个线程上专门用来跑 css 动画
- 所以有的时候你会发现,当你的 页面卡住了,css 动画依旧能够执行下去
4、看一下 图层
下面就是百度 原本的 图层,结构还是很简单的
找到那个 bottom_layer ,可以看到 是那个 position: fixed 导致了 图层,我们可以手动的把这个 fixed 改成 absolute
可以发现,以前 箭头 指着的 bottom_layer 图层 就这样消失了
- 很多 css 属性 都是可以导致 图层的出现的,比如 transform,will-change 等
- 而且 在这个的基础上,translate3d 和 will-change 还会启动 GPU 绘制图层
- 这样的话,绘制的 效率自然是大大提升,比 js 动画 要强了
- 但是要注意的是,额外图层 的绘制 会导致 内存的 消耗,就像之前有文章 讲过的 字节码 和机器码 一样
- 所以 使用 图层 的方式绘制 要讲究 适当,不要什么都来一波 css 技术红利
- 可能会有人说 BFC 和图层之间 又是什么关系呢?
- position: fixed 是属于 BFC 的,但是又 属于 layers,但是 可以看到 position: absolute 是属于 BFC 的,但是 又不属于 layers ,所以 要具体情况具体分析了
- (不过根据我的试验,发现 好像也就 一个 fixed 会创建图层 ,有兴趣的 同学 也可以试试,并且指出我的 错误)