Skip to content

浏览器工作原理及其实践

  目前的业务是通过原生应用通过 native 的 webview 来显示网页,所以需要了解下浏览器的原理。本文总结自极客时间的浏览器工作原理课程,旨在梳理浏览器底层机制,为前端开发和性能优化提供理论基础。

参考:极客时间 - 浏览器工作原理与实践

浏览器架构

多进程架构

现代浏览器采用多进程架构,以提高稳定性、安全性和性能。以 Chrome 浏览器为例,主要包含以下进程:

浏览器进程(Browser Process)

浏览器的主进程,负责:

  • 用户界面管理:地址栏、书签栏、前进后退按钮等 UI 元素
  • 标签页管理:创建、关闭、切换标签页
  • 安全性:处理安全策略、证书验证
  • 网络请求协调:协调各个渲染进程的网络请求
  • 文件系统访问:管理下载、文件访问权限

渲染进程(Renderer Process)

每个标签页通常对应一个独立的渲染进程,负责:

  • HTML 解析:将 HTML 文档解析成 DOM 树
  • CSS 解析:解析样式表,生成 CSSOM
  • JavaScript 执行:运行页面中的 JavaScript 代码
  • 页面渲染:将内容绘制到屏幕上
  • 事件处理:处理用户交互事件

进程隔离的优势: - 一个标签页崩溃不会影响其他标签页 - 不同标签页之间的 JavaScript 无法直接访问 - 提高了浏览器的整体稳定性

GPU 进程(GPU Process)

专门处理图形渲染任务:

  • 硬件加速:利用 GPU 加速页面绘制和动画
  • 3D 图形处理:WebGL、CSS 3D 变换等
  • 视频解码:硬件加速的视频播放

网络进程(Network Process)

处理所有网络相关任务:

  • HTTP/HTTPS 请求:发送和接收网络请求
  • DNS 解析:域名解析
  • TLS/SSL 加密:处理 HTTPS 加密通信
  • 缓存管理:管理 HTTP 缓存

进程间通信

浏览器进程和渲染进程之间通过 IPC(Inter-Process Communication) 进行通信:

  • 渲染进程通过 IPC 请求资源
  • 浏览器进程通过 IPC 发送用户输入事件
  • 渲染进程通过 IPC 通知浏览器进程页面状态变化

渲染流程

浏览器将网页从 HTML 转换为可视化页面的过程称为渲染流程,主要包括以下步骤:

1. 构建 DOM 树

HTML 解析过程

  1. 字节流 → 字符流:将网络接收的字节流转换为字符流
  2. 字符流 → TokenHTML 解析器将字符流解析成 Token
  3. Token → 节点:将 Token 转换为 DOM 节点
  4. 节点 → DOM 树:将节点构建成 DOM 树

解析特点: - 边下载边解析,不需要等待整个 HTML 下载完成 - 遇到 <script> 标签会阻塞解析,等待脚本执行完成 - 遇到 <link><style> 标签会并行下载 CSS

2. 样式计算

CSS 解析过程

  1. CSS 文本 → CSSOM:将 CSS 文本解析成 CSSOM(CSS Object Model)树
  2. 样式规则匹配:将 CSS 规则与 DOM 节点匹配
  3. 计算最终样式:处理继承、层叠、优先级,计算每个节点的最终样式

样式计算规则: - 继承:某些 CSS 属性会从父元素继承 - 层叠:多个样式规则可能应用到同一个元素 - 优先级!important > 内联样式 > ID 选择器 > 类选择器 > 标签选择器

3. 布局(Layout)

布局阶段计算每个元素在页面中的位置和大小:

布局流程

  1. 创建布局树:遍历 DOM 树,创建只包含可见元素的布局树
  2. 排除 display: none 的元素
  3. 排除 headscript 等不可见元素

  4. 计算布局:计算每个节点的几何信息

  5. 位置(x, y 坐标)
  6. 大小(width, height)
  7. 边距、内边距、边框

  8. 布局更新:当 DOM 或样式发生变化时,触发重新布局(reflow)

布局性能优化: - 避免频繁修改 DOM - 使用 transformopacity 代替修改布局属性 - 批量修改 DOM,减少布局次数

4. 分层(Layer)

为了优化渲染性能,浏览器会将页面分成多个图层:

分层策略: - 拥有 3D 变换的元素(transform: translateZ(0)) - 使用 will-change 属性的元素 - 视频、Canvas 等元素 - 有滚动容器的元素

图层优势: - 独立合成,互不影响 - 可以利用 GPU 加速 - 只重绘变化的图层

5. 绘制(Paint)

绘制阶段将每个图层的绘制指令记录到绘制列表中:

绘制内容: - 背景色、背景图片 - 边框 - 文字 - 阴影等视觉效果

绘制优化: - 减少绘制区域 - 使用 CSS 动画代替 JavaScript 动画 - 避免复杂的 CSS 效果

6. 合成(Compositing)

合成阶段将各个图层合成为最终的页面图像:

合成流程: 1. 主线程将绘制列表提交给合成线程 2. 合成线程将图层分块(tiles) 3. 光栅化线程将分块转换为位图 4. 合成线程将位图合成为最终图像 5. 显示到屏幕上

合成优势: - 合成操作在合成线程完成,不阻塞主线程 - 可以利用 GPU 加速 - 只更新变化的图层

JavaScript 引擎

V8 引擎架构

Chrome 使用的 V8 引擎是高性能的 JavaScript 执行引擎:

主要组件

  1. 解析器(Parser)
  2. 将 JavaScript 代码解析成抽象语法树(AST)
  3. 进行词法分析和语法分析

  4. 解释器(Ignition)

  5. 将 AST 转换为字节码
  6. 执行字节码

  7. 编译器(TurboFan)

  8. 将热点代码(hot code)编译成机器码
  9. 优化代码执行效率

执行流程

JavaScript 代码
解析器 → AST
解释器 → 字节码 → 执行
编译器(JIT)→ 机器码 → 执行

JIT(Just-In-Time)编译: - 监控代码执行频率 - 将频繁执行的代码编译成机器码 - 提高执行效率

内存管理

堆内存结构

V8 将堆内存分为几个区域:

  • 新生代(New Space):存放新创建的对象
  • 老生代(Old Space):存放长期存活的对象
  • 大对象空间(Large Object Space):存放大对象
  • 代码空间(Code Space):存放编译后的代码

垃圾回收

新生代垃圾回收: - 使用 Scavenge 算法 - 将新生代分为两个区域:From 和 To - 将存活对象复制到 To 区域 - 清空 From 区域,交换 From 和 To

老生代垃圾回收: - 使用标记-清除(Mark-Sweep)算法 - 标记存活对象 - 清除未标记的对象 - 使用标记-整理(Mark-Compact)算法整理内存碎片

增量标记: - 将标记过程分成多个小步骤 - 与 JavaScript 执行交替进行 - 减少长时间停顿

浏览器安全机制

同源策略(Same-Origin Policy)

同源策略限制不同源的网页之间的交互:

同源定义: - 协议相同(http/https) - 域名相同 - 端口相同

限制内容: - Cookie、LocalStorage 等存储数据 - DOM 访问 - AJAX 请求

跨域解决方案: - CORS(Cross-Origin Resource Sharing) - JSONP - 代理服务器 - postMessage

沙箱机制(Sandboxing)

渲染进程运行在沙箱环境中:

沙箱限制: - 无法直接访问文件系统 - 无法直接访问网络 - 无法直接访问操作系统 API

安全优势: - 即使渲染进程被攻击,也无法影响系统 - 恶意代码被限制在沙箱内 - 提高了整体安全性

HTTPS 安全传输

HTTPS 工作原理

  1. 证书验证:浏览器验证服务器证书
  2. 密钥交换:使用非对称加密交换对称加密密钥
  3. 加密通信:使用对称加密进行数据传输

安全特性: - 数据加密传输 - 防止中间人攻击 - 保证数据完整性

性能优化实践

渲染性能优化

  1. 减少重排和重绘
  2. 使用 transformopacity 代替修改布局属性
  3. 批量修改 DOM
  4. 使用 documentFragment 减少 DOM 操作

  5. 优化 JavaScript 执行

  6. 避免长时间运行的 JavaScript
  7. 使用 requestIdleCallback 执行非关键任务
  8. 代码分割,按需加载

  9. 优化资源加载

  10. 使用 CDN 加速资源加载
  11. 压缩资源文件
  12. 使用 HTTP/2 多路复用

内存优化

  1. 避免内存泄漏
  2. 及时清理事件监听器
  3. 避免循环引用
  4. 使用 WeakMap 和 WeakSet

  5. 优化对象创建

  6. 复用对象,避免频繁创建
  7. 使用对象池
  8. 避免创建大对象

总结

理解浏览器工作原理对于前端开发至关重要:

  1. 多进程架构提供了稳定性和安全性
  2. 渲染流程决定了页面显示效果和性能
  3. JavaScript 引擎的执行机制影响代码性能
  4. 安全机制保护用户数据和系统安全

掌握这些原理,可以帮助我们: - 编写更高效的代码 - 优化页面性能 - 解决复杂的浏览器兼容性问题 - 提升用户体验

参考