从输入 url 到页面渲染
发起网络前
1 缓存阶段
1.1 浏览器与服务器通信的方式为应答模式
- 浏览器发起 HTTP 请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中 HTTP 头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中
- 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
- 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
1.2 强制缓存
- 当浏览器向服务器发送请求的时候,服务器会将缓存规则放入 HTTP 响应的报文的 HTTP 头中和请求结果一起返回给浏览器,控制强制缓存的字段分别是 Expires 和 Cache-Control,其中 Cache-Conctrol 的优先级比 Expires 高
- Cache-Control(public,private,no-cache,no-store,max-age)
- Expires,服务器返回该请求的结果缓存的到期时间
1.3 协商缓存
- 协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
- 标识 (Etag / If-None-Match 优先级高于 Last-Modified / If-Modified-Since)
1.4 缓存位置
- from memory cache 内存中缓存,可快速读取,有时效性,一旦该进程关闭,则该进程的内存则会清空
- from disk cache 硬盘中缓存,需要对该缓存存放的硬盘文件进行 I/O 操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢
- 读取顺序 memory –> disk
1.5 总结
强制缓存优先于协商缓存进行,若强制缓存(Expires 和 Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since 和 Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,再存入浏览器缓存中;生效则返回 304,继续使用缓存
1.6 启发式缓存
如果响应中未显示 Expires,Cache-Control:max-age 或 Cache-Control:s-maxage,并且响应中不包含其他有关缓存的限制,缓存可以使用启发式方法计算新鲜度寿命。通常会根据响应头中的 2 个时间字段 ,Date 减去 Last-Modified 值的 10% 作为缓存时间
2 浏览器准备阶段
2.1 浏览器进程
- 浏览器进程,除标签页外的其他用户界面,前进,后退,地址栏,书签,及与其他进程合作,包括 UI 线程,网络线程
- GPU 进程,整个浏览器界面的渲染
- 网络进程,负责发起接受网络请求
- 渲染进程,控制显示 tab 标签内的所有内容,每个 tab 一个进程,一个主线程(main thread),多个工作线程(work thread),一个合成器线程(compositor thread),多个栅格线程(raster thread)
- 插件进程,控制网站使用的插件,如 flash
- 缓存进程
2.2 UI 线程工作
- 捕捉输入内容关键字,使用默认搜索引擎对应的 URL 去 DNS 查询地址
3 DNS 查询阶段
- DNS 域名解析过程,将域名,例如http://www.baidu.com,解析为 IP 地址的过程
- 浏览器缓存,浏览器会缓存 DNS 记录持续一定时间,不同的浏览器时间间隔不同,大约在 2-30 分钟
- 系统缓存,系统缓存主要存在/etc/hosts 中
- ISP 缓存,互联网服务提供商,如电信,联通,移动,ISP 提供了本地 DNS 服务器,用于提供 DNS 缓存服务
- 判断是否启用转发模式
- 如果未用转发模式,本地 DNS 就把请求发至 13 台根 DNS,根 DNS 服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个 IP。本地 DNS 服务器收到 IP 信息后,将会联系负责'.com 域'的这台服务器。这台负责'.com 域'的服务器收到请求后,如果自己无法解析,它就会找一个管理'.com 域'的下一级 DNS 服务器地址http://baidu.com给本地 DNS 服务器。当本地 DNS 服务器收到这个地址后,就会找http://baidu.com域服务器,重复上面的动作,进行查询,直至找到http://www.baidu.com主机
- 如果用的是转发模式,此 DNS 服务器就会把请求转发至上一级 DNS 服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根 DNS 或把转请求转至上上级,以此循环。不管是本地 DNS 服务器用的是转发,还是根提示,最后都是把结果返回给本地 DNS 服务器,由此 DNS 服务器再返回给客户机
发起网络
查询到 IP 地址后由浏览器进程中的网络线程发起请求
客户端对数据进行处理
发送数据包
- 应用层(应用层,表示层,会话层),应用程序处理
编码处理,控制何时建立通信,将数据发送给下一层 - 传输层,TCP 模块处理
根据应用层的指示,建立和断开连接,并提供将数据顺利发送到对端的可靠传输,面向连接的、可靠的流协议。通过校验和,序列号,确认应答,重发控制,连接管理,以及窗口控制等机制实现可靠性传输。以段为单位发送数据,MSS(在三次握手中得出)最大消息长度,是 IP 中不会被分片处理的最大数据长度。可利用 TCP 窗口提高速度,无需等待确认应答而可以继续发送数据的最大值,即使部分应答未返回,仍可使用下一个应答进行确认。重发控制,报文段丢失的情况下,同一个序号的确认应答将会被重复不断的返回,发送端如果连续三次收到同一个确认应答,则将对应的数据重发,称为高速重发控制。 - 网络层,IP 模块处理
通过 IP 地址传输到服务端 - 链路层,网络接口处理
包含的 MAC,数据在每次转发的过程中更换 MAC 地址,每个主机都维护着一张路由控制表,该表记录 IP 数据在下一步应该发给哪个路由器
接收数据包
- 网络接口的处理
根据所传递的数据类型,将数据传给对应的子程序,如 IP 类型,则传递给的处理 IP 的子程序 - IP 模块的处理
判断包首部中的 IP 地址与自己的地址是否匹配,根据数据查找上层协议,交给指定协议处理 - TCP 模块的处理
校验数据是否损坏,根据端口号确定具体的应用程序,接收完成,发送一个”确认回执“给发送端 - 应用程序的处理
应用程序接收发送端发送的数据
浏览器渲染
接收数据
- 网络线程接收到服务器的响应后,开始解析 HTTP 响应报文,然后根据响应头中的 Content-Type 字段来确定响应主体的媒体类型(MIME Type),如果媒体类型是一个 HTML 文件,则将响应数据交给渲染进程(renderer process)来进行下一步的工作,如果是 zip 文件或者其它文件,会把相关数据传输给下载管理器。
- 通知 UI 线程数据请求完成
- 浏览器进程发送 IPC 消息确认导航
- 浏览器进程通过 IPC 管道将数据传递给渲染进程
- 渲染进程接收到数据之后,又发送 IPC 消息给浏览器进程,告诉浏览器进程导航已经提交了,页面开始加载,与此同时,导航栏更新,安全提示符更新,访问历史列表更新
开始渲染
渲染进程的主线程将 html 进行解析构造 DOM 结构,生成 DOM 树,形成 DOM 树后不断向其中添加节点
知道 DOM 结构和每个节点的样式后,接下来确定每个节点的位置及其所占用的区域,该节点称为 layout 布局
主线程通过遍历 DOM 和计算好的样式生成 layout Tree。layout Tree 是和最终展示在界面上的一一对应的,DOM 树和 layout Tree 是不一样的,如 display:none 和伪类
主线程遍历 layout Tree 创建一个绘制记录表(Paint Record), 该表记录了绘制的顺序,并生成 layer Tree
-
绘制
- 将 layer Tree 和绘制顺序信息传递给合成器线程,合成器线程按照规则分图层
- 由于每个图层可能像页面的整个长度一样大,故合成器线程将图层切分为多个图块(tiles)
- 将每个图块发送给栅格化线程(Raster Thread)
- 栅格线程栅格化每个图块,并将它们存储在 GPU 内存中
- 当栅格完成时,合成器线程将收集称为“draw quads”的图块信息, 这些信息记录了图块在内存中的位置和在页面的哪个位置绘制图块的信息
- 根据信息合成器线程生成合成器帧(Frame)
- 该合成器帧通过 IPC 传送给浏览器进程
- 浏览器进程将合成器帧传送给 GPU
- GPU 渲染展示到屏幕
- 进行操作时,如滚动,会生成新的合成器帧,再传送到 GPU,再次渲染
其他
- 重排和重绘,改变元素尺寸位置属性后,会重新进行样式计算,及后续流程,称为重排;改变元素颜色属性时,不会触发重新布局,但还是会触发样式计算,称为重绘
- js 也运行在主线程,处理不善会导致卡顿,如涉及动画可使用 transform,仅在合成器线程和栅格线程中使用,不会和 js 抢主线程
- 渲染结束,渲染进程向浏览器进程发送 IPC 消息,告诉浏览器进程渲染完成,此时 UI 线程停止 tab 中的加载中图标