浏览器原理和实践

1. Chrome 浏览器的进程机制

1.1 为什么选择chrome 浏览器?

  1. 因为 Chrome、微软的 Edge 以及国内的大部分主流浏览器,都是基于Chromium 二次开发而来
  2. Chrome 是 Google 的官方发行版,特性和 Chromium 基本一样,只存在一些产品层面差异
  3. Chrome 是目前世界上使用率最高的浏览器,所以 Chrome 最具代表性

1.2 Chrome 打开一个页面需要启动多少个进程?

  1. 网络进程 — 网络请求相关
  2. 浏览器进程 — 浏览器主进程(协调、主控)
  3. GPU 进程 — 3D绘制
  4. 渲染进程 — 页面渲染,脚本执行,事件处理(每个tab页面一个)如果打开的页面有运行插件的话,还需要再加上插件进程

image.png

2. 单进程浏览器时代

单进程浏览器 —— 浏览器的所有功能模块都是运行在同一个进程里,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等

缺陷和问题:

  • 不稳定 —— 插件不稳定易导致整个浏览器崩溃;复杂的 javascript 代码引起渲染引擎崩溃;
  • 不流畅 —— 各个模块运行在同一进程,意味着同一时刻只有一个模块可以执行;
  • 不安全 —— 插件可以使用 C/C++ 等代码编写,通过插件可以获取到操作系统的任意资源,当你在页面运行一个插件时也就意味着这个插件能完全操作你的电脑。如果是个恶意插件,那么它就可以释放病毒、窃取你的账号密码,引安全性问题

典型场景:
当你正在用浏览器打开多个页面时,突然某个页面崩溃了或者失去响应,随之而来的是整个浏览器的崩溃或者无响应,然后你发现你给老板写的邮件页面也随之消失了,这时你的心情会不会和页面一样崩溃呢?

3. 多进程浏览器时代 —— 早期

Chrome 的页面是运行在单独的渲染进程中的,同时页面里的插件也是运行在单独的插件进程之中,而进程之间是通过 IPC 机制进行通信(如图中虚线部分)。

缺陷和问题的解决:

  • 解决不稳定问题 —— 页面和插件进程独立,互不影响
  • 解决不流畅问题 —— 只对当前页面渲染阻塞;
  • 解决不安全问题 —— Chrome 把插件进程和渲染进程锁在沙箱里面, 这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。

问题:当你从浏览器输入URL到页面呈现的过程中,到底发生了什么?

image.png

image.png

image.png

1. 浏览器渲染流程 —— DOM树构建

为什么构建DOM树?这是因为浏览器无法直接理解和使用 HTML,所以需要将 HTML 转换为浏览器能够理解的结构——DOM 树。构建 DOM 树的输入内容是一个非常简单的HTML 文件,然后经由 HTML 解析器解析,最终输出树状结构的 DOM。

image.png

2. 浏览器渲染流程 —— 样式计算

目的:计算DOM节点中的每个元素的具体样式

  1. 把 CSS 转换为浏览器能够理解的结
  2. 转换样式表中的属性值,使其标准化
  3. 计算出 DOM 树中每个节点的具体样式

3. 浏览器渲染流程 —— 布局阶段

布局:DOM 树和 DOM 树中元素的样式还不足以显示页面,我们还需知道 DOM 元素的几何位置信息。我们把这个计算过程叫做布局。

image.png

4. 浏览器渲染流程 —— 分层

分层:页面中的复杂效果如一些复杂的 3D 变换、页面滚动等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树。

image.png

5. 浏览器渲染流程 —— 生成图层绘制列表

绘制列表:

  1. 渲染引擎会把一个图层的绘制拆分成很多小的绘制指令,然后再把这些指令按照顺序组成一个待绘制列表
  2. 绘制列表中的指令其实让其执行一个简单的绘制操作,比如绘制粉色矩形或者黑色的线等

image.png

6. 浏览器渲染流程 —— 栅格化操作

栅格化操作:图层的绘制列表准备 → 主线程将绘制列表提交合成线程 → 合成线程将图层分为图块(tiles) →
栅格化 (将图块转换为位图) → GPU栅格化 (栅格化操作使用GPU,涉及到跨进程操作)

7. 浏览器渲染流程 —— 合成与渲染

合成与显示:所有图片栅格化 → 合成线程生成绘制图快命令(DrawQuad) → viz组件接受命令,将内容绘制在内存中 → 屏幕显示

问题:当你从初次进入产品页面,为什么会有 1-2 秒的白屏时间?

优化方向:

  1. 静态资源请求数量 —— 合并脚本,样式表
  2. 请求带宽 —— 移除重复脚本(tree shaking); 代码切割 (code spliting)
  3. 缓存利用 —— 添加Expires头,配置Etag
  4. 页面结构 —— 将样式表放在顶部,将脚本放在底部
  5. 代码层面 —— 执行脚本函数过程,页面阻塞;闭包导致内存泄漏等

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享