最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 浏览器缓存实践篇

    正文概述 掘金(一个__小白)   2021-01-20   442

    最近在复习浏览器缓存,在复习过程中产生了很多的疑问,决定来实际使用一下测试真实情况。理论知识参考的 (1.6w字)浏览器灵魂之问,请问你能接得住几个? 这篇文章。

    强缓存

    • Expires
    • Cache-Control

    Expires

    首先测试下 Expires,首先使用 Express 搭建一个本地服务器。使用 static 访问本地的 public 文件夹,通过配置 etag, cacheControl, lastModified 为 false,禁用所有的缓存。

    const express = require('express')
    const app = express()
    const port = 3000
    
    app.get('/hello', (req, res) => res.send('Hello World!'))
    app.use('/static', express.static('public', {
        etag: false,
        cacheControl: false,
        lastModified: false,
    }))
    
    app.listen(port, () => console.log(`Example app listening on port ${port}!`))
    

    启动起来后可以在本地访问多次看下状态都是 200,没有缓存,Response Headers 里面没有缓存相关的字段。 浏览器缓存实践篇

    然后我们添加上 Expires 字段测试一下。我们给所有请求的 Header 加上 Expires 字段,设置过期时间为请求后的 60 秒后。

    app.use('/static', express.static('public', {
        etag: false,
        cacheControl: false,
        lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
        }
    }))
    

    可以看到第一次请求 index.html 和 test.js 的 Response Headers 里面都有 Expires 字段,时间为发起请求 + 60 秒。

    浏览器缓存实践篇

    然后我们再次刷新,可以看到 test.js 直接从 memory cache 里面取的,看下后端的日志,也没有打印出来 /static/test.js 的请求 url,说明 Expires 生效了,但是对于 index.html 确没有生效,这里没有搞清楚原因,希望知道的指点一下。 60 秒后再次刷新,可以看到又是从后端后去资源了。

    浏览器缓存实践篇

    另外,Expires 是跟本地时间有关系的,我们也可以测试下。因为不好截图显示我修改了本地时间,在此就不截图了,具体操作是:先请求,然后修改本地时间到一分钟后,刷新,可以看到并没有缓存。


    Cache-Control

    然后测试 Cache-Control,文档里说到 Cache-Control 和 Expires 同时存在时,优先考虑 Cache-Control,所以我们直接加上 Cache-Control 字段测试一下。

    app.use('/static', express.static('public', {
        etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
        lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
        }
    }))
    
    

    继续刷新看结果,可以看到 Cache-Control 和 Expires 同时存在,但是 Expires 不生效了,每次都是 200 并且没有取缓存。

    浏览器缓存实践篇

    因为没有设置 max-age,Cache-Control 的默认值为 public, max-age=0,所以没有缓存效果,现在设置下 max-age 为 10 秒。

    app.use('/static', express.static('public', {
        etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
       	// 这里的 maxAge 是毫秒,但是 Response Header 中的 max-age 是秒单位
        maxAge: 10000,
        lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
        }
    }))
    

    刷新看结果,10 秒内直接取缓存。

    浏览器缓存实践篇

    然后测试下 Cache-Control 的其他设置值。

    1. no-cache 跳过强缓存,直接进入协商缓存
    app.use('/static', express.static('public', {
        etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
       	// 这里的 maxAge 是毫秒,但是 Response Header 中的 max-age 是秒单位
        maxAge: 10000,
        lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
          res.append('Cache-Control', 'no-cache');
        }
    }))
    

    刷新可以看没有强缓存,无 memory cache

    1. no-store 不进行任何缓存
    app.use('/static', express.static('public', {
        etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
       	// 这里的 maxAge 是毫秒,但是 Response Header 中的 max-age 是秒单位
        maxAge: 10000,
        lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
          res.append('Cache-Control', 'no-store');
        }
    }))
    

    刷新可以看没有强缓存,无 memory cache

    1. private/s-maxage 这两个字段用于代理服务器,没搞明白如何测试代理服务器,求助大家。

    协商缓存

    当强缓存失效后,会根据是否存在协商缓存字段进行协商缓存阶段

    • Last-Modified
    • ETag
    Last-Modified

    默认 lastModified 为 true,lastModified 设置为 true 时,会在 Response Headers 中添加 Last-Modified 字段,然后在下次请求该资源时把该字段放入 If-Modified-Since 中,服务器会根据资源的最近修改时间和 If-Modified-Since 进行对比,如果发现文件更新了,则返回 200,把最新更新时间放入 Last-Modified 中,如果没有更新,则返回 304,告诉浏览器直接用缓存。

    app.use('/static', express.static('public', {
        etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
       	// 这里的 maxAge 是毫秒,但是 Response Header 中的 max-age 是秒单位
        maxAge: 10000,
        // lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
          res.append('Cache-Control', 'no-cache');
        }
    }))
    

    第一次请求后再次直接请求 ,可以看到 index.html 和 test.js 都返回了 304,当我修改了 test.js 并保存后,可以看到 test.js 请求返回了 200。

    浏览器缓存实践篇 可以看到返回了 Last-Modified 为最新的修改时间,比 If-Modified-Since 时间晚。

    浏览器缓存实践篇

    文章里说到 Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。这里我测试了一下确实是这样的。 我写了个 js 去修改 index.html

    const fs = require('fs');
    
    const res = fs.readFileSync('./public/index.html');
    
    function sleep(time) {
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve();
        }, time)
      })
    }
    
    (async function() {
      await sleep(10000);
      for (let i = 0; i < 60; i++) {
        await sleep(10);
        fs.writeFileSync('./public/index.html', `${res} ${i}`);
      }  
    })()
    

    在 600 ms 内每 10 ms 去修改一次 index.html,可以看到最后获取到的 index.html里面的数字是 43,而实际上我的文件里内容是 59. 浏览器缓存实践篇 浏览器缓存实践篇

    E-Tag

    打开静态文件的 E-Tag 只需要去掉 etag: false,默认 etag 为 true

    app.use('/static', express.static('public', {
        // etag: false,
        // 去掉 cacheControl 的 false 设置
        // cacheControl: false,
        // 这里的 maxAge 是毫秒,但是 Response Header 中的 max-age 是秒单位
        // maxAge: 10000,
        // lastModified: false,
        setHeaders: function (res, path, stat) {
          res.append('Expires', new Date(new Date().getTime() + 60 * 1000));
          res.append('Cache-Control', 'no-cache');
        }
    }))
    
    

    可以看到设置了 etag 之后就不会有 “Last-Modified 能够感知的单位时间是秒” 的问题了。每次文件有修改都会更新到 ETag 浏览器缓存实践篇

    总结

    到这里文章就结束了,总结一下:

    1. Cache-Control 的 max-age 和 Expires 控制强缓存,有 Cache-Control,则 Expires 失效。
    2. 强缓存失效,Last-Modified 和 ETag 控制协商缓存。ETag 优先级比 Last-Modified 优先级高。
    3. 另外需要注意,因为我使用的 express.static 支持缓存,如果是 Get 或者 Head 请求,可以自己实现或者使用中间件实现缓存效果。

    另外有几个问题没有解决。

    1.index.html 不会从 memory-cache 取,我猜测可能是浏览器认为是入口页面不会 memory-cache,而 index.html 里面引入的 test.js 则可以 memory-cache。
    2.private 和 s-maxage 没有进行测试。
    

    下载网 » 浏览器缓存实践篇

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元