其次,如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间。哪怕文件可能没有变化,它也会自动更新,所以起不到缓存的作用。
强缓存
通常服务器会通知浏览器一个缓存时间,这个信息在 Cache-Control 和 Expires 中,浏览器通过这个判断是缓存否过期。如果时间未过期。则直接从缓存中取。这就是所谓的“强缓存”。
Expires
在 HTTP1.0 中。使用 Expires 字段来表示缓存的到期时间,即有效时间+当时服务器的时间。但是这种方式的缺陷是,用户只需要修改客户端本地时间,让客户端和服务器时间不一致时,浏览器就会判断缓存失效,然后重新请求资源。
Cache-control
Cache-Control 是一个 HTTP 协议中关于缓存的响应头,它可以由以下值组成:
max-age:用于设置缓存的最大周期。与 Expires 相反,它的时间是相对于请求的时间。
s-maxage:和 max-age 相同,仅用于共享缓存,如 CDN 缓存。
public:相应可以被任何对象缓存,即使是通常不可缓存的内容。
private:缓存只能被单个用户缓存,不能作为共享缓存(即代理服务器不可缓存)。
no-cache:可以缓存在客户端,但每次都必须去服务器检查新鲜度,来决定从服务器获取最新资源(200)还是读取缓存(304),即协商缓存。
no-store:不允许在客户端存储,每次都要从服务器请求新的资源。
协商缓存
如果未命中强缓存,即强缓存失效(可能是 Cache-Control 设置了 no-store 或 no-cache),则判断协商缓存。
Last-Modified & If-Modified-Since(HTTP1.0)
当第一次请求资源后,服务器会返回改资源最后一次修改的时间。之后再次请求时,服务器会对比 If-Modified-Since 和 Last-Modified 字段。如果两者相同,则表示资源未修改,返回 304 状态码。如果两者不同,则表示资源已经修改了,所以返回数据和 200 状态码(没有发送请求)。
但是如果服务器更新资源的时间单位为秒,而上面提到的方法是无法识别一秒内进行多次修改的情况的。同时如果资源更新的速度不到 1ms,也是无法生成新的最后修改时间的。为了避免这种情况,在 HTTP1.1 中出现了一组新的字段:Etag 和 If-None-Match。
Etag & If-None-Match (HTTP1.1)
Etag 是 HTTP1.1 的属性。它由服务器生成并返回给客户端,优先级高于 Last-Modified。
在 HTTP1.1 中,当浏览器第一次发起 HTTP 请求时,服务器回返回一个 Etag。浏览器第二次发起同一个请求时,客户端会发送一个 If-None-Match,它的值就是 Etag。服务器会比较浏览器发送过来的 Etag 和服务器的 Etag,如果相同就将 If-None-Match 的值设置为 false,并返回304,表示使用浏览器缓存。如果不同,服务器就将 If-None-Match 的值设置为 true,返回 200 和新的数据。
网页加载速度的加快绝不仅仅是网速加快就能完成的,在我们流畅访问的背后,浏览器存储和缓存机制也功不可没,希望本文能够帮助大家增加对这个机制的了解。
参考资料:
深入理解浏览器的缓存机制 https://www.jianshu.com/p/54cc04190252
一文读懂前端缓存 https://juejin.cn/post/6844903747357769742?utm_source=gold_browser_extension
浏览器的存储与缓存机制 https://blog.csdn.net/wantingtr/article/details/100559520