前端浏览器缓存是指浏览器在第一次请求网页资源时,将资源缓存到本地,以后请求相同的资源时,直接从缓存中读取,而不再向服务器发送请求,从而提高页面加载速度和减轻服务器负担的一种机制。
浏览器缓存分为两种:强缓存和协商缓存。
强缓存
强缓存是指浏览器在第一次请求资源时,服务器返回的响应头中会带有 Cache-Control
或 Expires
字段,用来标记资源的有效期。如果资源的有效期在当前时间之前,浏览器就直接从缓存中读取,而不再向服务器发送请求。
Cache-Control
字段包含多个值,其中比较常见的有:
max-age=<seconds>
:缓存的有效期,单位是秒。no-cache
:缓存但需要重新验证,每次请求时都会向服务器发送请求。no-store
:不缓存任何内容,每次都从服务器获取最新的资源。
Expires
字段指定了一个绝对时间,即资源过期的时间。当浏览器的时间在 Expires
的时间之前时,就会从缓存中读取资源。不过由于 Expires
字段是服务器返回的一个绝对时间,因此对于服务器和客户端的时间差会产生影响,所以在 HTTP/1.1 中已经逐渐被 Cache-Control
取代。
协商缓存
协商缓存是指浏览器在第一次请求资源时,服务器返回的响应头中带有 Last-Modified
或 ETag
字段,用来标记资源的最后修改时间或者唯一标识符。当浏览器再次请求该资源时,会带上 If-Modified-Since
或 If-None-Match
字段,向服务器询问该资源是否发生了变化。如果服务器返回状态码 304 Not Modified,表示资源未发生变化,浏览器就直接从缓存中读取,否则浏览器就会重新请求资源。
Last-Modified
字段指定了资源最后修改的时间,而 ETag
字段则是服务器为该资源生成的唯一标识符。如果服务器返回了 ETag
字段,那么浏览器就会优先使用 ETag
来验证资源是否发生了变化。
假设我们有一个静态文件 /static/index.js
,第一次请求时服务器返回的响应头如下:
HTTP/1.1 200 OK
Cache-Control: max-age=3600
Last-Modified: Fri, 05 May 2023 06:00:00 GMT
ETag: "abcde12345"
这表示资源可以被缓存 1 小时,最后修改时间为 2023 年 5 月 5 日 6 点,ETag 为 "abcde12345"。
当浏览器再次请求该资源时,请求头中会带上 If-Modified-Since
和 If-None-Match
字段:
GET /static/index.js HTTP/1.1
Host: example.com
If-Modified-Since: Fri, 05 May 2023 06:00:00 GMT
If-None-Match: "abcde12345"
服务器会检查资源是否发生了变化。如果资源未发生变化,服务器会返回 304 Not Modified 状态码,响应头中不会包含资源的内容,浏览器会直接从缓存中读取资源。如果资源发生了变化,服务器会返回新的资源内容,浏览器会更新缓存,并重新渲染页面。
需要注意的是,强缓存和协商缓存并不是互斥的,而是可以同时使用。当浏览器同时使用了强缓存和协商缓存时,会优先使用强缓存。只有在强缓存失效后,才会使用协商缓存。
浏览器缓存机制在 web 应用开发中非常重要,它可以有效地减少服务器的负担,提高用户体验。但是在一些情况下,缓存会导致应用出现问题,比如缓存过期导致用户看到的不是最新的内容,或者缓存内容过多导致浏览器性能下降。因此,在开发 web 应用时,需要合理地使用缓存机制,避免出现这些问题。