chrome的基本原理

120 阅读6分钟

前言

对于前端来说,编写web应用是我们重要的工作之一,而web应用载体则是浏览器。了解浏览器中的各个模块特性能让我们更好地写好、优化和设计高性能web应用。

chrome的多进程架构

chrome为何会采取多进程的架构呢?主要是因为如果使用的是单进程浏览器(IE6),那就意味着所有功能模块都要运行在一个进程之中,这些功能包括JS运行环境、渲染引擎等,这就会导致了当某一个模块出现问题报错之后,会使整个浏览器奔溃。

可以举一个很简单的例子:当JS代码中出现了无限循环的代码的时候,此时因为整个浏览器都是使用同一个进程,就会出现因为一个页面奔溃导致其他页面也同时奔溃的情况。

chrome分为以下几个进程:

  • 浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
  • 渲染进程。主要负责将HTML、CSS和JS渲染成为网页。我们熟知的V8引擎和渲染排版引擎Blink都在这个进程之中。
  • GPU进程。主要负责绘制UI和3D CSS。
  • 网络进程。主要负责网络资源加载,比如接口请求和图片、css文件、html文件和js文件下载等。
  • 插件进程。主要负责插件的运行。因为是另一个进程,所以就算插件崩了也不会对页面造成影响。

从以上我们可以知道,在chrome打开一个页面,至少都会有4个进程——浏览器进程、渲染进程、GPU进程和网络进程。

从输入URL到展示,这中间发生了什么?

结合chrome的进程来描述的话:

用户输入→处理输入信息→开始导航→发送url请求→获取响应数据→准备渲染进程→将获取的数据提交给渲染进程→确认文档提交→解析文档渲染页面→页面加载完成。

浏览器进程

在用户输入了网址后,浏览器进程获取到用户输入,判断用户输入的是域名还是**搜索内容。**如果是网址则通过IPC(进程间通信)的方式将其给到网络进程,等待网络进程的结果返回。如下图所示,当输入网址后,浏览器进程进入等待状态。

网络进程

网络进程获取到网址后,会先在本地缓存中查找该资源,如果有则重定向,无则将网址发送到DNS服务器中进行解析,以获取域名对应的IP地址。获取了对应的IP地址后,便开始请求对应的内容(html文件、css文件等)。当获取到响应头时,网络进程会通知浏览器进程,此时浏览器进程将会通知渲染进程准备渲染(同时页面也会清空)。当请求获取完毕后,网络进程便会通知渲染进程开始渲染。

渲染进程

渲染进程在接受到通知后,便开始解析html文件和css文件,生成对应的dom树styleSheets。要注意的是,这两个的生成是异步的。dom树和styleSheets可以在console中直接打印出来,图1为dom树,图2为styleSheets。

获取到dom树后,渲染进程便开始根据获取的CSS样式文件来计算每个dom的样式,这里涉及三个步骤,分别是:

  1. 将CSS样式(styel、link、style标签内的)转换为浏览器能读懂的格式——styleSheets。
  2. 将一些css的属性值标准化,比如我们熟知的font-weight中的bold,它会装换成700。
  3. 根据继承规则层叠规则计算每个dom节点的样式。

继承规则

基础规则其实就是将父元素的一些样式属性继承下来,比如我们熟知的font-size、color。

层叠规则

层叠规则指的是如果同一个dom上有多个样式定义并存在冲突,则按样式的优先级去进行选择。优先顺序为:!important > style > 类选择器 > class。同级的情况下,后定义的样式覆盖前样式。

布局

当计算好样式并与dom合并后会生成布局树,渲染进程就会开始根据布局树进行布局。

分层

当完成布局后,渲染器便开始对布局树进行分层操作。为什么要分层呢?这是因为在CSS中会有z-index等影响层叠效果的属性,如果做成分层的话,就能更加方便实现效果。图层分层是根据三个规则来划分的:

  • 拥有层叠上下文属性的元素会被提升为单独的一层,如z-index等,详细的可以看这里
  • 发生剪裁的。比如父元素限定了高宽导致有内容溢出的时候。
  • 如果不满足以上条件,则与父元素共为一层。

合成线程

当分层完成后,渲染器进程中的主线程便会将分层提交给合成线程进行合成。合成线程会将图层进行栅格化处理,生成很多小块。为什么要进行栅格化处理呢?因为页面往往要比可视窗口要大,那么对于页面展现来说,不在可视窗口范围的的部分优先度就会低,这样就能大大加速浏览器的首次加载的速度了。完成合成后,渲染器进程会通知主进程,渲染完成。至此,整个页面就结束了。

重排和重绘

了解了上面渲染过程,所以就能理解为什么重排比重绘的开销要大了。重排是因为元素的几何属性发生了变化导致,这就意味着要重新计算布局、图层大小,整个流程都要重新走一遍。但如果只是修改了颜色等绘制属性,那么渲染教程便可以跳过计算布局、图层大小的过程,大大减少了浏览器的开销。

结语

了解了基本过程,能减少我们在编码过程中产生无意的坑,提升效率。(本来打算2月发的,没想到拖延症加项目进度问题导致拖延到了3月末T_T)

参考