从输入 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 域名解析过程,将域名,例如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 服务器地址baidu.com给本地 DNS 服务器。当本地 DNS 服务器收到这个地址后,就会找baidu.com域服务器,重复上面的动作,进行查询,直至找到www.baidu.com主机
- 如果用的是转发模式,此 DNS 服务器就会把请求转发至上一级 DNS 服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根 DNS 或把转请求转至上上级,以此循环。不管是本地 DNS 服务器用的是转发,还是根提示,最后都是把结果返回给本地 DNS 服务器,由此 DNS 服务器再返回给客户机
发起网络
查询到 IP 地址后由网络进程发起请求
-
建立 TCP 连接(三次握手)
-
建立 TLS 安全连接
-
发送 HTTP 请求
-
服务器处理,返回数据
-
浏览器解析渲染页面
-
浏览器执行渲染 - 浏览器的网络线程收到 html 文档后,会产生一个渲染任务,并传递给渲染主线程的消息队列。主线程在循环机制的作用下,开始执行渲染任务。
-
html 解析 Parse
- 生成 DOM 树和 CSSOM 树
- 外部资源由专门的预解析线程处理,不会阻塞解析 HTML
- 解析过程中遇到 JS 会暂停,因为 JS 有可能操作 DOM
-
样式计算 Style
结合 CSSOM 树,遍历 DOM 树,依次计算每个节点的样式,得到带有样式的 DOM 树
-
布局 Layout
遍历 DOM 树,计算每个节点的集合信息,得到 Layout 树。DOM 树和 Layout 树并非一一对应,例如有些 DOM 节点是 display:none,不会渲染,所以不会出现在 Layout 树中
-
分层 Layer
对 Layout 树进行分层,将来某层改变后,仅对该层做处理,提升效率
-
绘制 Paint - 渲染主线程任务结束
生成绘制指令集,将绘制信息提交给合成线程
-
分块 Tiling - 合成线程工作
合成线程将每个图层进行分块,将块信息交给 GPU 进程
-
光栅化 Raster
GPU 进程开启多个线程完成光栅化,将每个块变成位图交给合成线程
-
绘画 Draw
- 合成线程拿到块的位图后,生成一个个 quad 信息,交给 GPU 进程,GPU 产生系统调用,提交给硬件,最终完成屏幕成像
- transform 发生在合成线程,不会对主线程有影响,所以效率高
-
-
渲染结束,渲染进程向浏览器进程发送 IPC 消息,告诉浏览器进程渲染完成,此时 UI 线程停止 tab 中的加载中图标
什么是 reflow,repaint?
- 修改尺寸,边距后需要进行
样式计算 - 修改颜色后需要
Paint - 这两步都在主线程中进行,所以会影响效率