Write By CS逍遥剑仙 我的主页: www.csxiaoyao.com GitHub: github.com/csxiaoyaojianxian Email: sunjianfeng@csxiaoyao.com
前端知识的深入绕不开浏览器原理的学习,本系列文章为笔者学习浏览器原理后整理的笔记,学习的过程以极客时间《浏览器工作原理与实践》为主线,对原文的重要知识点进行了归纳整理,针对其中的部分细节知识点查阅了大量资料进行扩展并梳理总结,其中有部分demo和图片参考自原文。
浏览器三大进化路线:应用程序 Web 化,Web 应用移动化,Web 操作系统化。早在2007年之前,市面上浏览器都是单进程的,即浏览器所有的功能模块运行在同一个进程中,因此不稳定、不流畅、不安全。
2008年发布的 Chrome 拆分为 3 种进程,除主进程外,页面运行在单独的渲染进程中,同时页面里的插件运行在单独的插件进程中,而进程间通过 IPC 机制进行通信(图中虚线部分)。
最新的 Chrome 浏览器包括 5 类进程:
打开 1 个页面,至少有 4 个进程:浏览器进程、网络进程、GPU 进程、渲染进程,可能有插件进程。
为了解决 资源占用 和 体系架构复杂 的问题,Chrome 官方团队2016 年使用 SOA
思想设计了新的 Chrome 架构,原来的模块会被重构成独立的服务,每个服务在独立的进程中运行,使用定义好的接口访问服务,通过 IPC 通信。
同时在性能受限的设备上 Chrome 还提供灵活的弹性架构,会将很多服务整合到一个进程中,从而节省内存占用。
图为简化的 TCP 网络四层传输模型,UDP与之相似,不同之处在于 TCP 头的信息保证了大数据块传输的完整性、可靠性,但牺牲了数据包的传输速度,三次握手 和 数据包排序校验机制 等过程把传输过程中数据包的数量提高了一倍。
HTTP 协议是建立在 TCP 连接基础之上的一种允许浏览器向服务器获取资源的协议。
构建请求行信息,如 GET /index.html HTTP1.1
2. 查找缓存
3. 准备 IP 地址和端口
使用 DNS
或 DNS缓存
获取对应IP
4. 等待 TCP 队列
Chrome TCP 队列机制:同一域名最多只能同时建立 6 个 TCP 连接,超出的请求会排队等待
5. 建立 TCP 连接
6. 发送 HTTP 请求
2. 断开连接
3. 重定向特殊情况
浏览器会在服务器返回时根据响应头中的 Cache-Control
字段的过期时长来设置资源缓存,下次请求直接读取未过期缓存。若缓存过期,浏览器则会发起网络请求,并在 HTTP 请求头 中带上资源 key
,如:If-None-Match:"4f80f-13c-3a1xb12a"
,服务器根据资源 key 值判断请求的资源是否有更新,若没有更新则仅返回 304 状态码,有更新则直接返回最新资源。
登录成功后会生成标识用户身份的字符串并写到响应头的 Set-Cookie
字段里,浏览器解析存到本地,下次请求自动在请求头的 Cookie
字段中添加该值。
1. 用户输入
2. URL 请求
3. 准备渲染进程
Chrome 默认会为每个打开的页面分配一个渲染进程,但如果新页面和当前页面属于同一站点(根域名+协议相同)则会复用父页面的渲染进程(process-per-site-instance)。
4. 提交文档
此处 文档 是指 URL 请求的响应体数据,浏览器进程发出 提交文档消息,渲染进程接收到后会和网络进程建立传输数据的 管道,文档数据传输完成后渲染进程返回 确认提交消息 给浏览器进程,浏览器进程更新浏览器界面状态,并更新 Web 页面。
5. 渲染阶段
下面将依次从 DOM、Style、Layout、Layer、Paint、Tiles & Raster、DrawQuad 分析渲染流程,详见《浏览器中的页面渲染》。
document 即 DOM 结构,区别于 HTML 的是,DOM 是保存在内存中的树状结构,可通过 JavaScript 来查询或修改其内容。
当渲染引擎接收到 CSS 文本时(link外部文件、style标签内、内联样式),会执行转换操作将 CSS 文本转换为浏览器可以理解的结构(styleSheets),在浏览器的 console 中可输入命令 document.styleSheets
查看。
根据 CSS 的 继承 和 层叠 规则计算每个 DOM 节点的样式并被保存在 ComputedStyle
结构内,可在开发者工具内查看。
除了 DOM 树和 DOM 树中元素的样式,显示页面还需要通过创建 布局树 和布局计算来得到 DOM 元素的几何位置信息。
在显示之前还要额外地构建一棵只包含可见元素布局树,遍历 DOM 树中的所有可见节点加到布局中。
计算布局树节点的坐标位置的计算过程非常复杂,此处略过,执行布局操作时会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,不合理,Chrome 下一代布局系统 LayoutNG 将解决这个问题。
创建布局后,渲染引擎还要为特定的节点生成专用的图层,并生成对应的图层树(LayerTree),在后面章节会介绍。
布局树的节点默认从属于父节点图层,满足下面两点中一点的元素可被提升为单独的一个图层:
1. 拥有层叠上下文属性
明确定位属性、定义透明属性、使用 CSS 滤镜等的元素拥有层叠上下文属性。
2. 需要剪裁(clip)的内容
当内容展示不下被隐藏或出现滚动条时,内容部分会单独创建一个层。
渲染引擎会对图层树中的每个图层进行绘制,首先会生成绘制列表,可以在开发者工具的 Layers 标签中选择 document 层查看实际绘制列表。
Tips: 图层绘制并非真正绘出帧图片,而是生成绘制指令列表,绘制过程即完成
绘制列表只是用来记录绘制顺序和指令,主线程会把该绘制列表 提交{commit) 给渲染引擎中的 合成线程 进行实际绘制操作。有的图层很大很长,但用户通过 视口(viewport)只能看到页面的很小一部分,为了减小开销,合成线程会将图层划分为 图块(tile),通常大小为 256x256 或 512x512,合成线程会优先把视口附近的图块栅格化转换成位图。
当所有图块都被光栅化,合成线程会生成绘制图块命令 DrawQuad 并提交给浏览器进程。浏览器进程里的 viz
组件根据 DrawQuad 消息绘制到内存中,最后显示在显示器上。
使用 CSS 的 transform 实现动画效果可以避开重排和重绘,直接在非主线程上执行合成动画操作,并不会占用主线程的资源,效率较高,在页面章节会深入讲解。
减少重排重绘的方法:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。