HTTP的场景实践 | 青训营

本文章通过编写代码对于 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 浏览器的缓存策略是,如果服务端开启强缓存,那么浏览器发现缓存中存在资源,仍进行协商缓存(服务器配置),因此服务器可以关闭协商缓存,保证其能够使用到强缓存的功能。

相关推荐
Find2 个月前
MaxKB 集成langchain + Vue + PostgreSQL 的 本地大模型+本地知识库 构建私有大模型 | MarsCode AI刷题
青训营笔记
理tan王子2 个月前
伴学笔记 AI刷题 14.数组元素之和最小化 | 豆包MarsCode AI刷题
青训营笔记
理tan王子2 个月前
伴学笔记 AI刷题 25.DNA序列编辑距离 | 豆包MarsCode AI刷题
青训营笔记
理tan王子2 个月前
伴学笔记 AI刷题 9.超市里的货物架调整 | 豆包MarsCode AI刷题
青训营笔记
夭要7夜宵2 个月前
分而治之,主题分片Partition | 豆包MarsCode AI刷题
青训营笔记
三六2 个月前
刷题漫漫路(二)| 豆包MarsCode AI刷题
青训营笔记
tabzzz2 个月前
突破Zustand的局限性:与React ContentAPI搭配使用
前端·青训营笔记
Serendipity5652 个月前
Go 语言入门指南——单元测试 | 豆包MarsCode AI刷题;
青训营笔记
wml2 个月前
前端实践-使用React实现简单代办事项列表 | 豆包MarsCode AI刷题
青训营笔记
用户44710308932422 个月前
详解前端框架中的设计模式 | 豆包MarsCode AI刷题
青训营笔记