type
status
date
slug
summary
tags
category
icon
password

浏览器从输入url到渲染页面的过程

1、从浏览器输入框输入域名地址
2、浏览器通过DNS解析域名地址为ip地址
3、tcp进行三次握手(首先浏览器向服务器发送一个信号(比喻:我要给你发送请求了,请做好准备),然后服务器接收到这个信号给服务器发送一个信号(比喻:我准备好了,请发送吧),然后浏览器发送一个信号(马上发生请求))
4.浏览器拿到html文件数据,对浏览器页面进行渲染
一个标签页存在一个浏览器进程,浏览器存在多个进程(浏览器进程,插件进程,GPU进程,渲染主进程)
渲染主进程包括下面五大线程
GUI渲染线程:负责渲染浏览器页面,解析html和css,形成dom树,cssom,render树,布局树,还有computed style(计算样式),GUI渲染线程与js引擎线程是互斥的,因为js可以改变dom树的变化,所以碰到js时会GUI会挂起,等到js引擎线程空闲时,GUI线程就会立刻执行
js引擎线程:称为js内核,负责处理js脚本程序(例如V8引擎),是单线程的,如果js执行时间过长可能造成页面渲染不连贯甚至渲染加载阻塞
事件触发线程:控制时间轮询,不属于js引擎线程(鼠标点击事件)
定时触发器线程:setTimeout 和 setInterval 不在js引擎线程,如果在js引擎线程中就会影响他的准确性
异步http请求线程:用于 XMLHttpRequest
5.断开链接(4次挥手)

浏览器渲染原理

当浏览器的网络进程收到html文档时,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。在事件循环的机制下,渲染主线程取出消息队列中渲染任务,开启渲染流程。
流程:HTML -> 解析 -> 样式计算 -> 布局 -> 分层 -> 绘制 -> 分块 -> 光栅化 -> 画

解析

解析过程中遇到CSS则解析CSS,遇到JS执行JS。为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载HTML中的外部CSS文件和外部JS文件。
如果主线程解析到link位置但是外部的css还未解析完成,主线程不会等待,继续解析后续的HTML,这是因为下载和解析 CSS 的工作是在预解析线程中进行的。这就是 CSS 不会阻塞 HTML 解析的根本原因
如果主线程解析到script位置,就会停止解析HTML,等待此script解析完成再解析HTML,
这里主要是因为js可以修改当前dom树,所以必须暂停dom树的生成,完成后得到dom树和cssom树,浏览器的默认样式,内部样式,外部样式,行内样式

样式计算

主线程会遍历得到的DOM树,依次为树中的每个节点计算出它的最终样式,称为Computed Style
在这个过程中,很多预设值会变成绝对值,比如red变为 rgb(255,0,0);相对单位会变成绝对单位,比如em会变成px

布局

布局阶段会依次遍历DOM树的每一个节点,计算每个节点的几何信息。例如节点的宽高,相对包含块的高度。比如`display:none`的节点没有几何信息,因此不会生成到布局树中;又比如伪元素选择器,它们不存在与dom树中,但是它们具有几何信息,所以会生成到布局树中,所以dom树与布局树不一致

分层

分层的好处在于,将来某一个层发生改变后,仅仅会对该层进行后续处理,从而提升效率。
滚动条,堆叠上下文,transform,opacity等样式都会或多或少的影响分层结果,也可以通过`will-change`属性更大程度的影响分层结果

绘制

渲染主程序会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。完成绘制后,渲染主线程将每个图层的绘制信息提交给合成线程,剩余工作交由合成线程完成,合成线程首先对每个图层进行分块,将其划分为更多的小区域,它会从线程池中拿取多个线程来完成工作。

光栅化

合成线程将块信息交给GPU进程,以极快的速度完成光栅化GPU进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块,如下:
notion image

合成线程拿到每个层每个块的位图后,生成一个个指引(quad) 信息,指引会标识每个位图应该花在屏幕的那个位置,以及会考虑到旋转,缩放等变形。变形发生在合成线程,与渲染祝线程无关,这就是transform效率高的本质原因。合成线程会把quad提交给GPU进程,由GPU进程产生系统调用,提交给GPU硬件,完成最终的屏幕成像。
notion image

面试题

reflow 重排(回流)

reflow的本质就是重新计算布局树。当进行了影响布局树的操作后,需要重新计算布局树,会引发layout,为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当js代码全部完成后再进行统一的计算。所以改动 属性造成reflow是异步完成的。所以当js获取属性时,可能造成无法获取最新的布局信息,浏览器在我们获取属性时立即reflow

repaint 重绘

repaint 的本质是重新根据分层信息计算了绘制指令,当改动了可见样式后,就需要重新计算,会引发repaint,由于元素的布局信息也属于可见样式,所以reflow一定会引起重排

为什么 transform 效率高

因为transform发生在渲染流程中的draw阶段,没有发生在渲染主线程中,不需要经过重排(reflow)和重绘(repaint),只需要在 GPU 内部基于绘制好的纹理进行变换或混合,就不需要布局和重绘
notion image

📎 参考文章

参考下文:这文章太棒了!
 
💡
欢迎您在底部评论区留言,一起交流~
CICDPromise的学习