原稿:语雀 · 浏览器渲染 & 前端存储 · 原目录:Web & 浏览器 › 浏览器渲染 & 前端存储
浏览器

现代浏览器通常由7部分构成: 2. 用户界面 : 地址栏、前进/后退按钮、书签菜单等。除浏览器主窗口显示的页面外,其他各个部分都属于UI。 4. 浏览器引擎 : 在用户界面和渲染引擎之间传送指令。 6. 渲染引擎 :负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。 8. 网络 :用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。 10. 用户界面后端 :绘制基本的窗口小部件,比如组合框和窗口。提供平台无关的API,在底层使用操作系统的UI方法。 12. JavaScript 解释器(JS引擎):用于解析和执行 JavaScript 代码。 14. 数据存储:持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。
多进程浏览器
现代浏览器通常都是多进程的
| ![]() |
多线程的浏览器内核
每一个 tab 页面可默认对应一个渲染器进程,这个进程是多线程的:UI 线程、JS 引擎线程、事件触发线程、网络请求线程等
从输入 URL 到页面加载完成
参考链接:【干货】浏览器是如何运作的?
URL 解析
当用户输入内容到地址栏后,浏览器进程的 UI 线程会捕捉输入内容
- 如果是一个地址,UI 线程会启动一个网络线程进行 DNS 查询,接着建立连接获取数据
- 如果是一串关键词,浏览器会调用默认配置的搜索引擎进行查询
DNS 查询
如果浏览器有缓存,直接从中获取 IP 地址,否则在系统缓存、路由器缓存查询,如果都没有命中,则向 DNS 服务器发起解析请求
建立 TCP 连接,进行 HTTP 传输
浏览器通过 DNS 获取到目标地址的 IP 后,通过 TCP 的三次握手建立好连接,浏览器便可以将 http 请求发送给服务器,服务端根据请求信息,得到数据后再响应给客户端
浏览器渲染过程
当响应数据准备完毕,网络线程会告知 UI 线程,之后 UI 线程会创建一个渲染器进程(内核)负责渲染页面。浏览器进程通过 IPC 管道将数据传输给渲染器进程,正式开始渲染 2. HTML 解析 & DOM 生成
主线程解析 html,html 文档会经过词法分析与树构造过程,生成一棵 DOM 树。期间遇到 CSS 文件、多媒体资源等,渲染器进程会创建额外的网络线程进行请求,并不会阻塞主线程对 html 的解析;但是遇到 js 文件时,主线程会暂停 html 解析,等待文档中的 js 文件加载、解析、执行完毕,之后才恢复 html 解析过程
|
重绘与重排
页面渲染过程中有两个概念与性能密切相关,即重排(reflow)和重绘(repaint)
- 重绘: 当改变元素的颜色属性时,不会重新触发布局,但会触发重新样式计算和绘制
- 重排 :当改变一个元素的尺寸、位置属性时,会对触发重新样式计算、布局、绘制以及后面的行为
行为 | 可能诱因 |
重排 |
|
重绘 |
|
Google Doc:CSS properties by style operation required 明确给出了引起重绘或重排的属性变更
渲染优化
重绘与重排都会占用主线程,而 JS 也运行在主线程上,因此会面临抢占主线程的问题,如果执行了不断导致重排重绘的动画,同时还有大量的 js 任务需要执行,则 js 可能不会在下一帧前即使归还主线程,表现为页面动画的卡顿
- requestAnimationFrame()
requestAnimationFrame 是浏览器用于定时循环操作的一个接口,类似于setTimeout,主要用途是按帧对网页进行重绘。设置这个 API 的目的是为了让各种网页动画效果(DOM动画、Canvas动画、SVG动画、WebGL动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。代码中使用这个API,就是告诉浏览器希望执行一个动画,让浏览器在下一个动画帧安排一次网页重绘,该方法会在每一帧被调用
- transform 动画、opacity 隐藏元素
根据上面的内容,栅格化只占用合成器线程和栅格线程,意味着无需和js抢夺主线程,而CSS3的 transform 实现的动画都基于栅格化过程,避免了和 js 抢占主线程,同时由于不用进行样式计算、布局、绘制等操作,节省了大量的运算时间
- 使用 DocumentFragment
在操作 DOM 时,如果需要增加大量的节点,可以先创建一个 DocumentFragment,对该文档片段进行操作,最后调用 append(frag),这样只会在最后一次插入片段时触发一次重绘重排
- 对参与动画的元素设置为绝对定位
避免对元素的父元素布局产生影响,尽量减小每次重新渲染的开销
rAF API
参考链接:
- requestIdleCallback和requestAnimationFrame详解
- The Anatomy of a Frame
- CSS3动画那么强,requestAnimationFrame还有毛线用?
为了保证页面流畅,通常浏览器会保证 FPS 至少为 60,每一帧的生命周期即涵盖了上述的浏览器渲染过程与 rAF API 的执行 2. 帧开始:OS 通过 Vsync 事件通知浏览器下一帧开始 4. 输入事件的处理:输入数据从 Compositor Thread 传递到 Main Thread上的事件处理程序。调度程序会尽力保证所有输入事件处理程序(touchmove,scroll,click)首先触发,每帧一次,但实际执行中可能有延迟 6. rAF:这是对屏幕进行可视更新的理想位置,因为已经获得新的输入数据,并且离 Vsync 事件很接近 8. HTML 解析:处理新添加的 HTML,创建 DOM 元素 10. 重新计算样式:任何新添加或修改的内容都需要重新计算样式,范围取决于更改的内容 12. 布局:计算每个可见元素的几何信息 14. 更新 Layer Tree:创建堆叠上下文和深度排序元素 16. 绘制:确定绘制顺序 18. 合成阶段:栅格线程光栅化各个图层的图块,合成器线程收集 Draw Quads,GPU 缓存 tiles 20. 帧结束:Draw Quads 会被提交给 GPU 线程,GPU 使用这些信息进行绘制 22. requestIdleCallback:当前面所有任务耗时没超过 16 ms,说明有当前帧有剩余空闲时间,此时就会执行 requestIdleCallback 里注册的回调
通过上述过程可以总结 rAF 的优点:
- 节省资源:rAF 在事件处理程序之后执行,把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成
- 改善视觉效果:rAF 在事件处理程序与渲染之间统一为每一帧安排了执行动画函数的时间,尽可能的保证了每一帧动画的连续
前端存储机制
cookies
存储位置:cookies 是网站为了标识用户身份而保存在客户端中的数据,它始终在同源的 HTTP 请求中携带,也就是会在客户端与服务端之间来回传递
存储大小:本地 cookies 数据大小不能超过4K,safari 和 chrome 对同一域名下 cookies 数量无限制
生命周期:cookies 在设置的过期时间之前一直有效,即使窗口或者浏览器关闭
跨域:不允许跨域,当手动指定 domain 时,允许给定的域以及其子域访问 cookie
