#基础
浏览器缓存是浏览器对用户访问的资源,根据响应头的缓存设置,自动进行的一种缓存存储。
浏览器每次访问资源时,浏览器都会触发浏览器缓存
浏览器缓存主要分为强缓存和协商缓存两种
#强缓存
强缓存会给缓存文件设置一个过期时间,未到过期时间,用户访问资源将始终访问浏览器缓存的文件,不会向服务器发送请求。如果过期了会重新请求文件,并更新强缓存。
强缓存是使用 Expires 和 Cache-Control 这两个响应头来控制的
Expires
- expires 设置一个 GMT 格式的字符串,超过时间则认为缓存过期
- 如果客户端和服务端的时间不同步,那么缓存会不在预期中触发,因此一般使用 Cache-Control
Cache-Control
- Cache-Control 设置一个 max-age=xx 的键值对,xx 为过期的秒数
- xx 秒内请求资源都会走本地缓存,不会请求服务端
jsasync powerCache(ctx, next) { const res = ctx.fileData ctx.set('content-type', 'text/html; charset=utf-8') ctx.set('Cache-Control', 'max-age=8') //设置强缓存,过期时间为8秒 ctx.body = res }
#协商缓存
协商缓存会给缓存文件设置一个标识,每次请求文件都会携带标识去请求服务器,如果标识相同,即文件未修改,返回 304 状态码;如果标识不同,即文件被修改过了,重新发送资源给浏览器,并更新协商缓存。
Etag
& If-None-Match
- 服务器在响应头中设置
Etag
,浏览器在请求头中设置If-None-Match
,如果 Etag 和 If-None-Match 相同,则返回 304 状态码,表示缓存未过期,浏览器直接使用本地缓存。 - 如果 Etag 和 If-None-Match 不同,则返回 200 状态码,表示缓存过期,浏览器重新请求资源,并更新协商缓存。
last-modified
& If-Modified-Since
- 服务器在响应头中发送 Last-Modified 字段,表示资源的最后修改时间。客户端下次请求时会在请求头中发送 If-Modified-Since 字段,如果资源的最后修改时间与客户端发送的时间相同或更晚,服务器会返回状态码 304 Not Modified,告诉客户端可以使用缓存。
#last-modified
& If-Modified-Since
的示例
jsasync chatCache(ctx, next) { const res = ctx.fileData const status = ctx.fileStatus const ifModifiedSince = ctx.request.header['if-modified-since'] if (ifModifiedSince && ifModifiedSince === status.mtime.toGMTString()) { ctx.status = 304 return } ctx.set('content-type', 'text/html; charset=utf-8') ctx.set('Last-Modified', status.mtime.toGMTString()) ctx.body = res }
和强缓存的区别是,协商缓存要在服务端实现一套对比请求头的逻辑,然后返回给浏览器是否要更新缓存。
#强缓存和协商缓存的区别和使用场景
强缓存
- 未到期前,命中缓存,不会请求服务器
协商缓存
- 命中缓存,每次都会请求服务器
使用场景
- 强缓存适合静态资源和不经常变化的资源。
- 协商缓存适合频繁变化的资源和需要确保数据最新的场景。
#使用缓存的优点
- 减少服务器的负担
- 加快客户端渲染的速度
- 避免了不必要的数据传输
#示例代码
#测试时不触发缓存的原因及解决方式
现在浏览器 f5 刷新时将不会触发缓存,因此想要测试需要
- 在一个新窗口提前打开控制台,输入 url 后可以看到触发了缓存
- 返回的文件中有指向自身的超链接
txthello world good morning <hr/> <a href="http://localhost:8000/cache/power">强缓存:</a> <hr/> <a href="http://localhost:8000/cache/chat">协商缓存:</a>