浏览器缓存知识

    0

浏览器缓存分强缓存和协商缓存

强缓存

不会向服务器发送请求,从缓存中读取资源,返回的状态码是200 如果响应头有expires、pragma或者cache-control字段,代表这是强缓存

  1. Expires HTTP/1.0 时间不准
  2. Cache-Control HTTP/1.1
  3. Cache-Control优先级高,覆盖Expires
  4. Cache-Control设置no-cache开启协商缓存
  5. 缓存过期之后,不管资源有没有变化,都会重新发起请求,重新获取资源

协商缓存

协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发送请求,由服务器根据缓存标识来决定是否使用缓存的过程。

  • 协商缓存生效,返回304
  • 协商缓存失效,返回200和请求结果
  1. Last-Modifed/If-Modified-Since
  • Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。
  • If-Modified-Since则是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。
  1. Etag/If-None-Match
  • Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。

  • If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

  • Last-Modifed缺点:

    • 文件不改变内容,仅改变修改时间
    • 1s修改多次,Last-Modifed只能精确到秒
  • 服务器优先验证Etag,若一致,继续比对Last-Modifed,最后判断是否返回304

  • Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

  • 可以这样设置来使用协商缓存

javascript
ctx.set('Cache-Control', 'public, max-age=0'); ctx.set('Last-Modified', xxx); ctx.set('ETag', xxx);

1645608159621rMCf36 1643808374278XG5csa

If-None-Match If-Modified-Since

区别

  1. 优先查找强缓存,没有命中再查找协商缓存
  2. 强缓存不会发请求到服务器,协商缓存会发请求,所以服务器文件更新了强缓存无法感知,协商缓存可以感知

刷新浏览器

  • 直接输入url地址,检查强制缓存
  • f5刷新 检查协商缓存,不检查强制缓存
  • ctrl+f5 不检查强制缓存和协商缓存,全部重新请求

分类型使用不同缓存

  1. html使用协商缓存
  2. css, image, js使用协商缓存,文件名使用hash

缓存优先级

  1. Service Worker
  2. Memory Cache(内存)
  3. Disk Cache(硬盘)
  4. Push Cache

请求流程

  1. 浏览器发送请求前,根据请求头的expires和cache-control判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步。
  2. 没有命中强缓存规则,浏览器会发送请求,根据请求头的last-modified和etag判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。
  3. 如果前两步都没有命中,则直接从服务端获取资源。

实战

使用koa模拟 https://github.com/zzfn/koa-server/blob/main/routes/cache.js

javascript
const Router = require('koa-router') const router = new Router({prefix: '/cache'}) module.exports = router router.get('/Expired', async ctx => { // ctx.response.lastModified = new Date(); const Expired=new Date(new Date().getTime()+10000).toUTCString() ctx.set('Expires',Expired) ctx.body={ now:new Date().toUTCString(), Expired } }) router.get('/cache-control', async ctx => { // ctx.response.lastModified = new Date(); const Expired=new Date(new Date().getTime()+10000).toUTCString() ctx.set('Cache-Control','max-age=10') ctx.body={ now:new Date().toUTCString(), Expired } }) router.get('/etag', async ctx => { console.log(1) // ctx.response.lastModified = new Date(); const Expired=new Date(new Date().getTime()+10000).toUTCString() ctx.set('Etag','1123') ctx.status = 304; ctx.body={ a:1, now:new Date().toUTCString(), Expired } }) router.get('/Last-Modified', async ctx => { // ctx.response.lastModified = new Date(); const Expired=new Date(new Date().getTime()+10000).toUTCString() ctx.set('Cache-Control','max-age=10') ctx.body={ now:new Date().toUTCString(), Expired } }) module.exports = router
评论区

共有评论 0

暂无评论