浏览器架构
浏览器架构演进:
- 单进程架构:所有模块运行在同一个进程里,包含网络、插件、JavaScript运行环境等。
- 多进程架构:主进程、网络进程、渲染进程、GPU进程、插件进程。
- 面向服务架构:将原来的U儿、数据库、文件、设备、网络等,作为一个独立的基础服务。
浏览器进程
浏览器是一个复杂的软件,它通常会将不同的任务分配给多个进程来提高性能和安全性。以下是常见的浏览器进程:
渲染进程
内部是多线程实现,主要负责页面渲染,脚本执行,事件处理,网络请求等。在浏览器中,渲染进程通常使用 HTML、CSS 和 JavaScript 来解析和渲染网页。渲染进程会将 HTML、CSS 和 JavaScript 文件解析成 DOM(文档对象模型)、CSSOM(CSS 对象模型) 和 JavaScript 对象,然后使用这些对象来渲染网页。
JS 引擎和渲染引擎通信
- 解析执行 JS。
- XML 解析生成渲染树,显示在屏幕。
- 桥接方式通信。
渲染进程的多线程工作流程
- 网络线程负责加载网页资源。
- JS 引擎解析 JS 脚本并且执行。
- JS 解析引擎空闲时,渲染线程立即工作。
- 用户交互、定时器操作等产生回调函数放入任务队列中。
- 事件线程进行事件循环,将队列里的任务取出交给 JS 引擎执行。
Chrome 运行原理
如何展示网页
浏览器地址输入 URL 后发生了什么:
输入处理
- 用户 URL 框输入内容后,UI 线程会判断输入的是一个 URL 地址还是一个 query 查询条件。
- 如果是 URL,直接请求站点资源。
- 如果是 query,将输入发送给搜索引擎。
开始导航
- 当用户按下回车,UI 线程通知网络线程发起一个网络请求,来获取站点内容。
- 请求过程中,tab 处于 loading 状态。
读取响应
- 网络线程接收到 HTTP 响应后,先检查响应头的媒体类型(MIME Type)。
- 如果响应主体是一个 HTML 文件,浏览器将内容交给渲染进程处理。
- 如果拿到的是其他类型文件,比如 Zip、exe 等,则交给下载管理器处理。
主进程寻找渲染进程
- 网络线程做完所有检查后,会告知主进程数据已准备完毕,主进程确认后为这个站点寻找一个渲染进程。
- 主进程通过 IPC 消息告知渲染进程去处理本次导航。
- 渲染进程开始接收数据并告知主进程自己已开始处理,导航结束,进入文档加载阶段。
渲染进程加载资源
- 收到主进程的消息后,开始加载 HTML 文档。
- 除此之外,还需要加载子资源,比如一些图片,CSS 样式文件以及 JavaScript 脚本。
渲染进程构建渲染树
- 构建 DOM 树,将 HTML 文本转化成浏览器能够理解的结构。
- 构建 CSSOM 树,浏览器同样不认识 CSS,需要将 CSS 代码转化为可理解的 CSSOM。
- 构建渲染树,渲染树是 DOM 树和 CSSOM 树的结合。
渲染进程进行页面布局
- 根据渲染树计算每个节点的位置和大小。
- 在浏览器页面区域绘制元素边框。
- 遍历渲染树,将元素以盒模型的形式写入文档流。
渲染进程页面绘制
- 构建图层:为特定的节点生成专用图层。
- 绘制图层:一个图层分成很多绘制指令,然后将这些指令按顺序组成一个绘制列表,交给合成线程。
- 合成线程接收指令生成图块。
- 栅格线程将图块进行栅格化。
- 展示在屏幕上。
前端性能 Performance
- 时间都花在哪里。
- 什么情况下卡顿。
首屏优化
- 压缩、分包、删除无用代码。
- 静态资源分离。
- JS 脚本非阻塞加载。
- 缓存策略。
- SSR。
- 预置 loading、骨架屏。
渲染优化
- GPU 加速。
- 减少回流、重绘。
- 离屏渲染。
- 懒加载。
JS 优化
- 防止内存泄漏。
- 循环尽早
break
。 - 合理使用闭包。
- 减少 Dom 访问。
- 防抖、节流。
- 使用异步 JavaScript(消息队列,微任务)可以使得主线程在等待请求返回结果的同时继续往下执行。
- Web Workers。