从输入 URL 到浏览器显示页面发生了什么?
浏览器的进程:
- 主进程:负责调度
- 渲染进程:每个页面都有单独的渲染进程(同一站点会复用)
- 网络进程
- GPU进程
- 插件进程
浏览器的主要步骤
- 在浏览器进程中输入
url
地址开始导航。并准备渲染进程 - 在网络进程中发送请求,将响应后的结果提交给渲染进程处理
- 渲染进程会返回确认的消息给浏览器进程,更新浏览器的导航栏等。
- 渲染进程开始解析页面,并加载页面中所需资源
- 渲染完毕(主进程也会收到消息,停止加载动画),展示结果
请求过程
**Queuing**
:请求发送前会根据优先级进行排队,同时每个域名最多处理 6 个 TCP 链接,超过的也会进行排队,并且分配磁盘空间时也会消耗一定时间~~Stalled~~
~~ : 请求发出前的等待时间(处理代理,链接复用) ~~**DNS lookup**
: 查找DNS
的时间**initial Connection**
: 建立 TCP 链接时间**SSL**
:SSL
握手时间(SSL
协商)~~Request Sent~~
~~ : 请求发送时间(可忽略) ~~**Waiting**
(**TTFB**
) : 等待响应的时间,等待返回首个字符的时间-
**Content Dowloaded**
: 用于下载响应的时间
- 蓝线:
DOMContentLoaded
:DOM
构建完成的时间 - 红线:
Load
: 浏览器所有资源加载完毕
渲染过程
渲染的时间顺序,流水线可分为如下几个子阶段:
构建 DOM 树、样式计算、布局阶段、分层、绘制(分块、光栅化和合成)。
- 构建DOM树:将HTML文件解析成DOM树
- 样式计算
- 将 CSS 解析成
CSSOM
(document.styleSeets
) - 属性值标准化
- 计算出DOM树中每个元素具体样式
- 将 CSS 解析成
- 布局阶段
- 创建布局树:将 DOM 树中可见节点,添加到布局树中
- 计算节点渲染到页面的坐标位置。(layout)
- 分层
- 对布局树进行分层 (根据定位属性、透明属性、transform 属性、clip 属性等)生产图层树
- 绘制
- 将不同图层进行绘制,转交给合成线程(属于渲染进程)处理。最终生产页面,并显示到浏览器 (Painting,Display)
- 合成线程会将图层划分为图块,然后转化为位图(光栅化)
- 光栅化完成后提交绘制指令给浏览器进程,生成页面显示。
- 将不同图层进行绘制,转交给合成线程(属于渲染进程)处理。最终生产页面,并显示到浏览器 (Painting,Display)
重排
重绘
重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。
直接合成
CSS 的 transform 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作
总结
- 大多数阶段是在渲染进程里执行的,但是 raster 和 display 则在 GPU 进程中执行。
- 流水线各个阶段都依赖上一步的结果,从头开始运行是代价是非常昂贵的
- 渲染进程的主线程的任何事情都会跟JS竞争(互斥关系),意味着其实JS也会阻塞渲染主线程其他任务的执行