一、浏览器组成
首先,浏览器分为三个部分,分别为用户界面、渲染引擎和浏览器引擎
现代浏览器一般采用多进程架构(打开方式:chrome
-> 任务管理器),大致为:浏览器进程、GPU
进程、渲染进程(标签页)*n、网络进程等
我们从chrome
的任务管理器可以看到不同的进程,如:浏览器进程、GPU进程等
1.进程与线程
进程
进程是操作系统分配资源和独立运行的最小单位,进程之间使用IPC(Inter Process Communication)
进行通信。
线程
线程是程序执行的最小单位,一个进程由一个或多个线程组成。
进程与线程的关系
进程与进程之间的通信是通过IPC(Inter Process Communication)
进行通信。(通俗理解:进程就是我们一个组,线程就是我们组内的每一个成员)。
2.采用多进程的优劣
优点
-
早期是单进程架构,不稳定(如果多个页面都在一个进程里面运行,如果某一个线程出问题,就会导致整个进程的崩溃,因此早期单进程的架构是不稳定,多进程就可以避免这个问题)
-
站点隔离,安全性和沙箱化(多个进程之间相互隔离,提供了一个隔离的环境)
缺点
-
占用内存过多
-
提高了通信成本(跨部门协作)
3.如何解决这些缺点?
早期的浏览器进程
合并之后的浏览器进程
将Network Process、UI Process、Stroage Process、Device Process
都合并到了Browser Precess
进程中,作为单独的线程去运行
浏览器组成小结
如下面这个框架图所示:浏览器组成分为:浏览器进程、渲染进程、GPU
进程,多个进程之间都是通过IPC
来进行通信的。
二、导航流程
浏览器输入URL
回车之后发生了什么?
1.处理输入
在地址栏输入URL
之后,浏览器进程的UI线程(UI thread
)会捕捉到你的输入,然后UI
线程会判断你输入的内容是URL
还是搜索词,如果是URL
则直接访问相应的URL
,如果是搜索词则会拼接上默认的搜索引擎进行访问
URL
:网络线程获取资源
keyword
:拼接默认搜索引擎
2. 开始导航
网络线程(Network thread
)获取资源。开始进行DNS
解析,TCP
连接等
3. 读取响应
网络线程读取响应头Content-Type
,针对不同类型做出不同动作。例如下图,就代表要渲染的为html
页面
4.查找渲染器进程
网络线程首先会检查资源是否安全,如果是安全的,浏览器进程就会找一个渲染进程进行对接。
5.提交导航
当资源和渲染进程都准备就绪时,浏览器进程发送IPC
给渲染进程确认。
6.导航完成
渲染进程接收数据,回复浏览器进程确认提交,浏览器进程就会把地址栏、标签、历史记录更新。到这里,整个导航流程就完成了。
导航流程小结
三、渲染流程
到了渲染进程之后,当我们的渲染进程拿到了html
,就开始逐行解析html
。
1.构建DOM
主线程解析HTML
,构建DOM
树,创建document
对象,遇到CSS
、图片资源就会进行加载,如果遇到JS
被阻塞。JS
的阻塞是因为JS
里可能存在修改DOM
的代码。
2. 计算样式
主线程解析CSS
,确定每个DOM
节点的样式(自定义样式+浏览器默认样式)
3. 构建Layout树
主线程遍历DOM
和计算样式生成Layout
只包含“可见”元素。比如:head
,display
为node
的节点不可见伪元素的content
可见。
4.创建Layer图层树
为了方便地实现3D
变换、页面滚动、z-index
等效果,会生成图层树。
分层规则:1. 拥有层叠上下文属性 2.需要剪裁(clip
)的地方
5.绘制顺序表
图层的绘制拆分成很多绘制指令,然后再把这些指令按照顺序组成一个绘制顺序表。
6. 栅格化
前面的五个步骤产生的都是数据,栅格化就是将数据转化为图片的过程。
栅格化是将向量图形格式表示的图像转化成位图用于显示器或者打印机输出的过程。
6-1.图层分块
图层太大【合成线程】会进行分块处理,再把图块交给【栅格线程】处理
6-2.合成
【栅格线程】会生成DrawQuads
(保存图块绘制信息),生成【一帧画面】。
【GPU进程】可以加速栅格化。
7.显示
【GPU
进程】会接收合成器帧,最终渲染显示在屏幕上。
帧: 显示器上看到一幅静止的画面。
帧率:一秒时间内显示画面的次数,60fps
达到流畅。即1帧16ms
。
渲染流程小结
四、优化手段
1.避免JS阻塞
(1)<script />
标签放底部
(2)加上async、defer
属性
async: js
加载完成之后,会立即执行js
defer: js
加载完成之后,按照顺序执行js
JS
长时间占用主线程,造成“丢帧”。
Jank
: <美军俚>(为躲避地面高射炮火而)同时改变飞行高度和方向, 闪避。
window.requestAnimationFrame
requestAnimationFrame
会在每一帧执行之前,留出一部分时间来执行js
。
在react 16
中也采用了类似的做法,从而有分块执行的能力:时间分片
参考文档:React Fiber原理解析
2.重排
修改影响布局的样式,导致重排。
3.重绘
修改非几何的样式,比如颜色,仅仅会触发重绘。
读写操作分离、缓存布局信息、离线修改DOM
。
参考文档:浏览器重绘(repaint)重排(reflow)与优化[浏览器机制]
五、总结
当我们通过了解浏览器内部的一些原理,可以帮助我们写出对浏览器更友好的代码。现代浏览器一直致力于探索如何提供更好的用户体验。书写对浏览器友好的代码,反过来也能提供友好的用户体验。
强烈推荐: Inside look at modern web browser (part 1) 系列讲解