翻看之前的学习笔记,发现浏览器工作原理的笔记干货满满,决定整理分享出来,和麻油们一起复习这个天天和我们打交道的东西,面试、开发、日常积累都用得上。😃
笔记较长,分为四篇,麻油们按需食用。
- 浏览器原理之大体看看
- 浏览器原理之 JS、V8
- 浏览器原理之页面
- 浏览器原理之网络安全
01. 开篇
浏览器三大进化路线
- 应用程序 Web 化:浏览器/服务器(B/S)架构应用,如视频、音频、游戏。
- Web 应用移动化:PWA(解决 性能不及原生应用、离线用户无法使用、无法接收消息推送、没有移动端入口)。
- Web 操作系统化:利用 web 技术构建纯粹的操作系统,如 ChromeOS;浏览器底层结构往操作系统架构发展。
前端核心诉求演进
- 脚本执行速度:ES6 >> 7 >> 8、WebAssembly。
- 前端模块化开发:WebComponents。
- 渲染效率:Chrome 的下一代布局方案 LayoutNG,渲染方案 Slim Paint。
学习目标
- 评估 Web 开发项目的可行性:了解浏览器如何工作的,才能更准确地决策
- 从浏览器原理的高度来审视页面:发现问题,解决问题
- 在快速的技术迭代中把握本质:在技术不断变化的环境下抓住核心脉络
02. 一个页面四个进程
进程 & 线程
进程
一个进程就是一个程序运行实例。
启动一个程序时,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据、一个执行任务的主线程,这样的一个运行环境叫进程。
线程
线程不能单独存在,必须由进程来启动和管理。多线程可以并行处理任务。
关系
- 进程中任一线程执行出错,都会导致整个进程的崩溃。
- 线程之间共享进程中的数据。
- 当进程被关闭时,操作系统会回收进程所占用的内存。即使进程中的任意线程内存泄露,这些内存也会被正确回收。
- 进程之间的内容相互隔离。进程间的通信依赖 IPC 机制。
进程 & 浏览器
单进程浏览器
2007 年之前,大部分浏览器都是单进程的。网络、插件、JS 运行环境、渲染引擎等所有功能模块运行在同一进程里。
单进程浏览器的问题:
- 不稳定:视频、游戏等插件崩溃,复杂 JS 代码引起渲染引擎崩溃,会进一步导致整个浏览器崩溃。
- 不流畅:所有模块运行在同一线程中,脚本或插件可能会导致页面内存泄露,让浏览器卡顿。
- 不安全:使用 C、C++编写的插件可以获取操作系统的任何资源,脚本也可以通过浏览器漏洞获取系统权限,引发安全问题。
多进程浏览器
最新 Chrome 浏览器,包括 1 个浏览器主进程、1 个 GPU 进程、1 个网络进程、多个渲染进程和多个插件进程。
- 浏览器主进程:界面展示、用户交互、子进程管理、存储功能。
- GPU 进程:UI、3D 效果。
- 网络进程:网络资源加载。
- 渲染进程:HTML+CSS+JS >>> 交互网页,排版引擎 Blink、JS 引擎 V8 在里面运行。sandbox
- 插件进程:插件运行。部分系统支持 sandbox。
多进程浏览器的问题:
- 更高的资源占有:每个进程都会包含公共基础结构的副本,消耗跟多的内存资源。
- 更复杂的体系架构:各模块之间的耦合性高、扩展性差,很难适应新的需求。
面向服务的架构(未来)
2016 年,Chrome 使用 Services Oriented ArchItecture(SOA)的思想设计了新的 Chrome 架构。
功能模块 >>> 独立的服务(运行在独立的进程中),访问服务需使用定义好的接口通过 IPC 通信。✔ 高内聚、松耦合、易维护扩展
基础服务
- Profile 进程
- UI 进程
- GPU 进程
- 网络进程
- 文件进程
- 设备进程
- Audio 进程
- Video 进程
- ...
基础服务类似于操作系统底层服务,上层才是 浏览器主进程、渲染进程、插件进程。
在资源不足的设备是哪个,可以将基础服务合并到浏览器主进程。
03. TCP 完整传输
网络层(IP)
将数据包送达目标主机。
网络层,在数据包上 附加 IP 头(解析 IP 头)。(源、目标 IP 地址)
传输层
把数据包送达应用程序。添加或解析 UDP 头。(源、目标端口号)
UDP
User Datagram Protocol 用户数据包协议
TCP
Transmission Control Protocol,传输控制协议。
建立连接、传输数据(接收端对每个数据包进行确认)、断开连接,保证数据完整传输。
04. HTTP 请求流程
(1)构建请求
构建请求行信息,准备发起网络请求。
(2)查询缓存
浏览器缓存包括 disk cache、memory cache、service worker cache,查询缓存失败才会进入网络请求。
(3)准备 IP 地址和端口
DNS 解析域名返回 IP(DNS 数据缓存服务)。端口从 URL 中取,没有使用默认的 80 或 443。
(4)等待 TCP 队列
chrome 同一域名同时最多只能建立 6 个 TCP 连接,超出的进入排队等待状态。(图片等静态资源多使用 CDN)
(5)建立 TCP 连接
(6)发送 HTTP 请求
(7)服务器处理请求
(8)服务器响应请求
(9)断开 TCP 连接
图片来源声明:极客时间——浏览器工作原理与实践
05. 从输入 URL 到页面展示
图片来源声明:极客时间——浏览器工作原理与实践
(1)用户输入
地址栏根据用户输入的内容生成完整的 URL。
地址栏会判断输入的关键字是搜索内容还是请求 URL,如果是搜索内容则使用默认的搜索引擎合成新的带搜索关键字的 URL,如果是 URL 则完整化处理。
按下回车键后,标签栏小图标的地方显示 loading 状态。页面底部会显示 正在等待 xxx.xx.xx 的响应。
(2)URL 请求过程
-
浏览器主进程通过 IPC 把 URL 请求发送到网络进程;
-
网络进程收到 URL 后,查询本地缓存,有返回,没有进入网络请求流程;
-
DNS 解析、建立 TCP 连接、发送 HTTP 请求、服务端处理请求返回数据(断开连接);
-
网络进程收到响应,开始解析响应头,
发现状态码 301 或 302 就读取 Location 字段重定向(重头开始),200 就继续处理请求,
Content-Type 值为 stream 之类的就把请求交给浏览器的下载管理器结束,是 html 就继续。
(3)准备渲染进程
一般 chrome 会为每一个页面分配一个渲染进程。但如果从 A 页面打开 B 页面,A/B 页面属于同一站点(域名协议相同),那 B 页面会复用 A 页面的渲染进程。
(4)提交文档
- 浏览器主进程发"提交文档"的消息给渲染进程;
- 渲染进程收到消息后和网络进程加你传输数据的管道;
- 文档数据传输完成,渲染进程返回"确认提交"的消息给浏览器主进程;
- 浏览器主进程更新界面状态,包括安全状态、地址栏 URL、更新前进后退历史状态、web 页面。(这个时候才卸载当前页,回收内存 ❓❓)
(5)渲染阶段
- 渲染进程开始页面解析,子资源加载;
- 页面渲染完成,渲染进程发消息,浏览器主进程收到后停止标签图标上的加载动画。
06. 渲染流程
(1)构建 DOM 树
浏览器无法直接理解和使用 HTML,需要将 HTML 转换为浏览器可以理解的结构--DOM 树。
(2)样式计算
- 将 CSS 文本,转换为 styleSheets,标准化样式表中的属性值(计算值);
- 按继承规则、层叠规则计算出节点具体样式,保存在 ComputedStyle 中。
(3)布局阶段
- 根据 DOM 树和 ComputedStype 生成布局树(所有可见节点);
- 计算布局树节点的坐标位置;
- 执行布局操作:将布局计算的结果重新协会布局树。
(4)分层
3D 变换、页面滚动、z-index 排序等效果,渲染引擎需要为这些特定的节点生成专用的图层,生成对应的图层树。
- 拥有层叠上下文属性的元素会被提升为单独的一层,如 filter、opacity、z-index、fixed...
- 需要裁剪 (clip) 的地方会被创建为图层。如 200x200 的带滚动条的 div 分为三层,文字层、滚动条、容器层
(5)图层绘制
绘制图层树的每个图层,把一个图层的绘制拆分成多个绘图指令,输出待绘制列表。
(6)格栅化(raster)操作
- 渲染进程的主线程吧绘制列表提交给合成线程;
- 合成线程将图层划分为图块(tile),256x256 或 512x512;
- 合成线程按视口附近的图块优先生成位图,渲染进程维护一个格栅化(图块>>位图)的线程池,完成所有图块格栅化;
- 格栅化过程都会使用 GPU 加速,渲染进程 IPC 将生成位图的指令发给 GPU 线程,GPU 生成的位图并保存在 GPU 内存中。
(7)合成和显示
- 所有图块格栅化完毕,合成线程生成绘制图块的指令"DrawQuad"提交到浏览器主进程;
- 浏览器主进程的 viz 组件接受指令,根据指令将页面内容绘制到内存中,再将内存显示在屏幕上。
**DOM >> Style >> Layout >> layer > Paint(sheet) >> ** (主线程)CPU
tiles >> raster >> draw quad >> display (合成线程、GPU 进程、浏览器主进程)GPU
三个重要的名词
重排
更新元素的几何属性,如改变元素宽高等,浏览器会触发重新布局,触发后面整个的渲染流水线更新,开销大。
Layout >> layer > Paint(sheet) >> tiles >> raster >> draw quad >> display
重绘
更新元素的绘制属性,如改变背景色等,没有几何位置变化,因此跳过布局阶段直接进入绘制阶段,更新后续流程,执行效率比重排高。
Paint(sheet) >> tiles >> raster >> draw quad >> display
合成
更改不需要布局、绘制的属性,直接进入合成阶段,如 transform 实现动画效果,执行效率比重绘高。
tiles >> raster >> draw quad >> display
那些年面试,有没有被问过重排重绘,如果减少优化性能..... O(∩_∩)O