浏览器
# 1. URL 到页面渲染
# 2. 回流和重绘
回流(重排):重新生成 DOM 树及进行后面一系列流程。
- width、height、padding、margin、left、top、border 等几何属性变化。
- DOM 节点增减或移动。
- 读写 offset 族、scroll 族和 client 族属性。
- 调用 window.getComputedStyle 方法。
重绘:跳过了生成布局树和建图层树的阶段,直接生成绘制列表,然后进行后面一系列流程。
DOM 样式发生变化,且没有影响几何属性。
合成(GPU 加速):直接跳过布局和绘制流程,直接进入非主线程处理的部分,即直接交给合成线程处理。
利用 CSS3 的 transform、opacity、filter 属性。
提示
重绘不一定导致回流,但回流一定发生了重绘。
# 3. 浏览器的缓存机制
作用:
- 降低网络延迟,加快网页加载。
- 减少网络带宽消耗。
- 降低服务器压力,提高并发性能。
浏览器缓存分为强制缓存和协商缓存,浏览器发起请求后,先回判断该请求资源是否有缓存,无缓存则向服务器发送请求。
有缓存先判断强制缓存是否生效(Expires / Cache-Control / Pragma,优先级:Expires < Cache-Control < Pragma),当强制缓存生效,则会返回内存中的缓存(Memory Cache)或硬盘中的缓存(Disk Cache),状态码为 200。
Expires:Expires 的值是一个 HTTP 日期和 Last-Modified 结合使用,在浏览器发起请求时,会根据系统时间和 Expires 的值进行比较,如果系统时间超过了 Expires 的值,缓存失效。由于和系统时间进行比较,所以当系统时间和服务器时间不一致的时候,会有缓存有效期不准的问题。Expires 的优先级在三个 Header 属性中是最低的。
Cache-Control:Cache-Control 是 HTTP/1.1 中新增的属性,在请求头和响应头中都可以使用,常用的属性值如有:
- max-age:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效。
- no-cache:不使用强缓存,需要与服务器验证缓存是否新鲜。
- no-store:禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源。
- private:专用于个人的缓存,中间代理、CDN 等不能缓存此响应。
- public:响应可以被中间代理、CDN 等缓存。
- must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证。
Pragma:Pragma 只有一个属性值,就是 no-cache ,效果和 Cache-Control 中的 no-cache 一致,不使用强缓存,需要与服务器验证缓存是否新鲜,在 3 个头部属性中的优先级最高。
若强制缓存失效,将进行协商缓存(Last-Modified / ETag,优先级:Last-Modified < ETag),这时浏览器会携带缓存标识向服务器发起请求。
Last-Modified/If-Modified-Since:Last-Modified/If-Modified-Since 的值代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存。
ETag/If-None-Match:ETag/If-None-Match 的值是一串 hash 码,代表的是一个资源的标识符,当服务端的文件变化的时候,它的 hash 码会随之改变,通过请求头中的 If-None-Match 和当前文件的 hash 值进行比较,如果相等则表示命中协商缓存。ETag 又有强弱校验之分,如果 hash 码是以 "W/" 开头的一串字符串,说明此时协商缓存的校验是弱校验的,只有服务器上的文件差异(根据 ETag 计算方式来决定)达到能够触发 hash 值后缀变化的时候,才会真正地请求资源,否则返回 304 并加载浏览器缓存。
由服务器根据缓存标识决定是否使用缓存,若协商缓存生效,继续使用缓存,返回 304 状态码;若协商缓存也失效,那代表该请求的缓存失效,重新获取请求结果。
浏览器策略:
- 同一个标签下,普通刷新请求 HTML 文件时,会在请求头添加
Cache-Control: max-age=0
,过期时间为 0,不会走强缓存。 - 如果没有强缓存(Pragma、Cache-Control、Expires),但有协商缓存 Last-Modified,则缓存的寿命就等于响应头里面 Date 的值减去 Last-Modified 的值除以 10,直接使用缓存资源,返回状态码 200。
function getExpirationTime(responseDateTime, lastModifiedTime) { const dateTimestamp = getTimestamp(responseDateTime) const lastModifiedTimestamp = getTimestamp(lastModifiedTime) const freshnessLifetime = (dateTimestamp - lastModifiedTimestamp) / 10 const expirationTime = new Date(dateTimestamp + freshnessLifetime).toLocaleString() function getTimestamp(date) { return new Date(date).getTime() } return expirationTime }
1
2
3
4
5
6
7
8
9
10
11
12
13- 同一个标签下,普通刷新请求 HTML 文件时,会在请求头添加