浏览器缓存

Jan 16, 2019 00:00 · 1787 words · 4 minute read js

什么是浏览器缓存

如今web的应用可以说种类丰富体积庞大, 通常一个入口页面就需要加载非常多的资源, 如果每一次打开页面都从服务器上获取这些资源无疑增加了服务器负担,也使用户等待更长的时间, 于是浏览器缓存出现了, 它的作用就是在用户本地缓存已浏览的网页部分资源, 以便在下次打开时能够直接使用这些资源而不是向服务器重新请求这部分资源.

根据 HTTP Archive,在排名最高的 300,000 个网站(按照 Alexa 排名)中,所有下载的响应中几乎有半数可由浏览器缓存,这可以大量减少重复的网页浏览和访问。当然,这并不意味着您的特定应用有 50% 的资源可以缓存。一些网站的资源 90% 以上都可以缓存,而其他网站可能有许多私密或时效要求高的数据根本无法缓存。

资源加载过程

资源加载过程

  1. 浏览器在加载资源时,先根系这个资源的http header 判断是否命中强缓存, 如果命中则直接冲缓存中加载资源. 命中强缓存后,浏览器不会像服务器发送任何请求,直接使用本地缓存的资源

  2. 当强缓存没有命, 浏览器会向服务器发送请求, 服务器依据资源的http header 验证这个资源是否命中协商缓存, 如果协商缓存命中, 则服务器会返回这个请求但不会返回这个资源的数据(http response 304), 否则服务器会返回资源的数据(http responce 200)

缓存原理

  1. 浏览器首次与服务器请求资源时, 服务器返回资源的同时还会在response的header上添加用于描述响应的内容类型、长度、缓存指令、验证令牌等的header, 如下图(缓存最多120s, 并提供一个验证令牌(“x234dff”))

http-request

  1. 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来
  2. 浏览器如果再请求这个资源,会先从缓存中寻找,找到这个资源后,根据它第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前(即120s内),就能命中缓存(强缓存) 浏览器加载缓存资源后结束.

强缓存

  1. 浏览器向服务器发送协商请求(请求头中包含 If-None-Match: x234dff 该值与上一次请求的响应中Etag相同), 如果资源在服务器端未改变, 怎服务器返回(304 notModified)响应

http-cache-control

协商缓存

  1. 如果资源在服务器端发生了改变, 则服务器会返回(200 OK)响应,同时返回新的资源数据, 浏览器收到数据后会更新资源的缓存与Etag等 response header信息

http-cache-control-highlight

Expries与Cache-Control

Expires(http1.0)或Cache-Control(http1.1)是http response header 的标准头信息, 它们都表示资源在客户端缓存的有效期

Expries是http1.0中提出的, 使用绝对时间,例如: “Expires: Sun, 07 Jan 2029 23:58:48 GMT” 由于服务器时间可能与客户端存在较大的时间差等问题,在http1.1提出了新的header Cache-Control, 它有多个指令可供使用, 最常见的如下:

指令 说明
no-store 直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
no-cache 不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载
max-age=86400 浏览器以及任何中间缓存均可将响应(如果是“public”响应)缓存长达 1 天(60 秒 x 60 分钟 x 24 小时)。
private, max-age=600 客户端的浏览器只能将响应缓存最长 10 分钟(60 秒 x 10 分钟)。

注意:如果cache-control与expires同时存在的话,cache-control的优先级高于expires

【Last-Modified,If-Modified-Since】与 【ETag、If-None-Match】

这两组都是http header的标准头信息, 用于协商缓存,与Expries 一样 【Last-Modified,If-Modified-Since】使用的是绝对时间, Last-Modified 是服务器最近一次响应时添加在 response header 中的信息 如: “Last-Modified: Sun, 07 Jan 2029 23:58:48 GMT”, 在协商请求时会在请求头中添加 If-Modified-Since 信息 如: “If-Modified-Since: Sun, 07 Jan 2029 23:58:48 GMT” 其值与上一次服务返回的 Last-Modified 值相同, 用于帮助服务器判断资源是否需要重新下发. 这组标准头存在的问题与Expries一样, 所以就有了 【ETag、If-None-Match】他们使用的是资源的指纹, 但资源发生变化时对应的指纹才会变化

缓存策略

这篇文章 有很好的指导意义