谈谈http缓存

关于缓存

这部分主要是想谈谈,关于文件缓存的几个标志以及它们的优先级,另外还想谈谈 react 中的缓存使用

缓存的优先级标志

当使用本地缓存的时候,可以根据是否需要向服务器验证本地缓存是否依旧有效,而将缓存分为协商缓存和强缓存,根据名字的字面意思,可以知道那些需要向服务器验证的是协商缓存。

这里,想简单聊一下,几个标注的优先级以及它们如何衍进的,为什么需要这么多种标志用来判断是否缓存的了。

对于我们常用的 http 请求,我们一般通过控制 Cache-control 和 Expire 两个字段来控制缓存,对于 expires 的使用,可以如“expires:过期时间”的格式使用;对于 Cache-control 可以通过如值“public,max-age=xxx 秒”的格式使用,表示在 XXX 秒内再次访问该资源,均使用本地缓存。这两者都是强缓存,但优先级 expires 低于 Cache-control。看到这里,好像关于缓存的问题应该解决的七七八八了,但其实这两种方式还存在一个致命的问题,如果在 xxx 秒后文件未更新,是不是还要请求了?如果是在毫秒内更新又该怎么办了?

接下来,来就让我们从全链路的角度来看看,看看为了使得文件可以在毫秒级别的程度进行更新,几个标志依次是如何做的。

1. 首先,我们约定过期时间(expires/Cache-control,后者相比前者更加稳定,_前者可以在浏览器端随意修改_),但如果时间到了,内容并没有更新,那该如何解决了 _文件+expires_
2. 那就在添加一个文件最新修改时间的对比,服务器告诉浏览器一个字段 last-modified,当浏览器向服务器请求时候,就带上字段 if-last-modified(也就是上次服务器给的 last-modified),如果服务器发现与现在自己的 last-modified 不一致就更新,但是这种方式只能精确到秒,所以这之间的改变是无法感知的 _文件+expires+last-modified_
3. 接下来添加一个文件内容唯一对比标记 Etag(服务器告诉浏览器,响应头),与浏览器告诉服务器的标志头(if-None-Match,请求头,其实就是上次服务器给的 Etag)进行比对 _文件+expires+last-modified+max-age+Etag_ (由于 expires 不太稳定,带上 max-age 且优先级更高,Etag 优先级也高于 last-modified)。但如果过期时间未到,文件有更新了,浏览器本身无法主动感知服务器文件的变化,那又该如何解决了?
4. 接下来,不缓存 html,为静态文件添加 md5/hash 标志,解决浏览器无法跳过缓存过期时间主动感知文件变化的问题(本质就是名字不同,就不会去判断缓存)。(其他亦或者 CDN 的方式进行缓存)

特别地,地址栏回车,页面链接跳转、新开窗口以及前进后退,Expires/Cache control 和 last-modified/Etag 都是有效的。但F5刷新会使得Expires/Cache control无效,F5+Ctrl则会让以上都失效

缓存的使用

在上一段落,谈到了一些关于缓存的标志,接下来聊聊如何使用。关于在常用的 http 请求中的使用,如 axios 中的使用,可以查阅文档解决,这里不在讨论,只要理解了几种字段头表述的含义,使用起来应该就没有什么问题了。

写到这里,如果你经常使用 React,一定会有疑问,React 中是否又使用到了缓存了。
其实 React 中我们也常常使用缓存,只是很多时候因为我们直接使用 create-react-app 创建项目,其底层 webpack 配置已经把 React 涉及到的缓存都配置好了。

写到这里,不妨再来谈谈为什么 React 需要缓存。在编写 React 代码的时候,我们会引入一些包,比如 loadsh 等,对于这些一直不变的内容,当我们因业务代码改变刷新页面的时候,当然希望这些不变的内容不会随着业务代码的重新加载而再次加载,因为这能极大提高我们的加载速度,因此这时自然而然就希望利用缓存。but,怎么让浏览器知道我们某些文件是新的,有的是没有变化的了,这时候 hash 值的作用就凸显出来了,通过判断文件的 hash 值是否变化进而判断文件是否被修改。在 webpack 主要是如下的配置:

output: {
    filename: "[name].[contenthash].js",
    chunkFilename: "[name].[contenthash].js", //浏览器会判断名字是否修改来选择是否加载新的还是使用缓存
    },

你可能感兴趣的:(网络,https)