本文章通过编写代码对于 Edge 浏览器涉及的请求中的缓存策略展开具体分析。
基本环境
搭建环境,使用 pnpm 作为包管理工具
bash
bash
复制代码
mkdir learn-http-cache
cd learn-http-cache
pnpm init
npm i nodemon -g
pnpm i express
配置脚本(package. json):
json
json
复制代码
{
"scripts":{
"dev": "nodemon index.js"
}
}
创建一个静态服务器 (index. js):
javascript
javascript
复制代码
const express = require('express')
const app = express()
const option = {}
app.use(express.static(__dirname, option))
app.listen(3000, () => {
console.log('http://localhost:3000/index.js')
})
pnpm dev
运行服务器并通过浏览器打开 http://loaclhost:3000/index.js
可以看到我们刚刚书写的代码。
Ctrl+Shift+I 打开开发者工具,找到 network,按照提示 Ctrl E
开始录制和 Ctrl+R
刷新页面得到浏览器发出的请求信息。点击可以查看请求的详情信息,并据此判断浏览器的缓存策略。
解读信息
分析头部信息
我们打开开发者工具得到了如下信息。通过响应的状态码为 304,我们大致可以倒推这是一次协商请求得到的结果:我们浏览器向服务器请求资源 index. js,服务器响应 304,标识资源未修改,服务器不返回资源,浏览器从缓存中读取资源。
继续往下看,我们查看浏览器发送的请求(Request Headers),可以看到这两个字段, 这两个字段只有在协商请求的时候才会出现,并作为服务器判断资源是否新鲜来作为是否响应最新资源的依据。
If-Modified-Since 记录的是缓存资源的修改时间。在浏览器发起请求准备获取网络资源时,会现在缓存中查找同名资源,并校验其强缓存时的信息判断资源是否新鲜,如果资源已超过保质期,就会向服务器发起协商缓存请求,将缓存中的文件的信息发送给服务器。
If-None-Match 是根据文件生成的 hash 值。具体算法由服务端决定。
下面是 Response Headers 响应体的头部信息: Cache-Control 字段表示,强缓存其资源并维持 0 秒的时间。 Last-Modified 字段用于浏览器的下一次协商缓存,其值到时将作为请求头字段 If-Modified-Since 的值。表示文件的最后一次修改时间。 Etag 字段用于浏览器的下一次协商缓存,其值到时将作为请求头字段 If-None-Match 的值。是根据文件内容生成的 hash 值。
初步结论
我们分析的请求和响应都是在我们刷新后得到的,因此我们分析的是第二次请求,我们并不知道第一次请求的内容,但是根据第二次请求的信息,我们可以得知。第一次请求应该是一次正常的请求:浏览器没有缓存文件,直接向服务器请求,服务器响应状态码 200 并返回一个文件。根据第二次响应的结果,服务器返回时指定了浏览器缓存该文件,并设置 max-age=0 的缓存时间,这意味着浏览器缓存了该文件,并且每次使用该缓存文件时都需要向服务器发起协商缓存的请求。
验证结论
我们在请求服务器的另外一个文件,并提前录制下这个请求,就可以看到浏览器是如何实现强缓存通信的了。
开始录制: 访问 http://localhost:4000/package.json
,获取到一次网络请求,我们来分析一下这次请求: 可以看到第一次请求浏览器没有的资源时,浏览器发送的不是协商缓存 (没有 If-Modified-Since 和 If-None-Match 字段),服务器响应 200,并通过 Cache-Control 告诉浏览器缓存该资源并设置缓存时间为 0,意味着以后请求该资源都需要发送协商缓存的请求。
刷新页面,这次浏览器的缓存中存在资源,于是进行了协商缓存。
修改配置
现在我们修改服务器配置延长强缓存的时间
vbnet
vbnet
复制代码
const option = {
maxAge: '1d',
}
预测结果:根据之前的分析,如果我们再次请求资源,浏览器会发现缓存中的资源仍是 max-age=0,于是重新请求,而我们的服务器这次返回 200,因为 Cache-Control 的值已经改变。浏览器会更新资源在缓存中的信息。接着如果我们再发起一次请求,这次浏览器会直接从强缓存中读取,并且不会发送协商缓存。 第一次请求符合预期(last-Modified 字段也发生了更新):
第二次请求不符合预期(强缓存并没有生效):
在服务器强制关闭协商缓存:
vbnet
vbnet
复制代码
const option = {
etag: false,
lastModified: false,
maxAge: '1d',
}
再次运行两次,可以看到第一次更新了资源,第二次使用了缓存。
结论
Edge 浏览器的缓存策略是,如果服务端开启强缓存,那么浏览器发现缓存中存在资源,仍进行协商缓存(服务器配置),因此服务器可以关闭协商缓存,保证其能够使用到强缓存的功能。