想象你每天早上去便利店买牛奶。缓存机制就像老板问你:"还是拿和昨天一样的盒装鲜奶吗?" 如果牛奶没过期(缓存有效),直接拿走不用付钱(不请求服务器);如果过期了(缓存失效),老板才会去仓库拿新的(重新请求)。
关键角色:
Cache-Control
:便利店老板的备忘录,写着"鲜奶保质期3天"ETag
:牛奶盒上的唯一编号,用来确认是不是同一批货Last-Modified
:牛奶的生产日期# 首次请求响应头
Cache-Control: max-age=3600 # 1小时有效期
ETag: "abc123"
此时浏览器直接把资源存到内存(memory cache)或磁盘(disk cache),1小时内重复请求直接读取缓存,不会产生任何网络请求(Chrome DevTools看到灰色from disk cache
)
当缓存过期后,浏览器带着「身份证」问服务器:
# 二次请求头
If-None-Match: "abc123" # 上次的ETag值
服务器对比ETag:
304 Not Modified
(空body,省流量)// Node.js设置响应头(Express示例)
app.get('/static/logo.png', (req, res) => {
// 强缓存1年(适用于带hash的静态资源)
res.set('Cache-Control', 'public, max-age=31536000, immutable')
// 禁止缓存(敏感数据)
// res.set('Cache-Control', 'no-store')
// 缓存但每次验证(适合频繁更新的API)
// res.set('Cache-Control', 'no-cache')
})
指令对比表:
指令 | 效果 | 适用场景 |
---|---|---|
max-age=3600 |
缓存有效期3600秒 | 静态资源 |
no-cache |
缓存但每次必须验证 | 需要实时性的数据 |
no-store |
禁止存储任何缓存 | 敏感数据(如支付接口) |
immutable |
即使过期也直接使用 | 带hash的静态文件 |
// 用文件内容生成ETag(避免时间戳导致的误判)
const crypto = require('crypto')
const fileContent = fs.readFileSync('data.json')
const etag = crypto.createHash('md5').update(fileContent).digest('hex')
app.get('/api/data', (req, res) => {
res.set('ETag', etag)
// 处理协商缓存
if (req.headers['if-none-match'] === etag) {
return res.status(304).end()
}
res.json({ data: 'new content' })
})
app.use(express.static('public', {
maxAge: '1y',
immutable: true // 关键!告诉浏览器不用验证
}))
// 强制跳过浏览器缓存(调试用)
fetch('/api/user', {
headers: {
'Cache-Control': 'no-cache', // 添加该头让浏览器强制验证
'Pragma': 'no-cache' // 兼容旧浏览器
}
})
# 源服务器响应头
Cache-Control: public, max-age=600 # 告诉CDN缓存10分钟
CDN-Cache-Control: public, max-age=3600 # CDN覆盖设置(部分厂商支持)
iOS Safari有时会无视no-store
:
// 添加随机参数绕过缓存
fetch(`/api/items?t=${Date.now()}`)
某些浏览器在「前进/后退」时直接使用内存缓存:
// 页面初始化时主动验证
window.addEventListener('pageshow', (event) => {
if (event.persisted) { // 从缓存恢复时触发
location.reload()
}
})
Network面板过滤:
(from disk cache)
→ 强缓存生效禁用缓存调试:
Disable cache
(等效于Cache-Control: no-store
)强制刷新:
Ctrl+Shift+R
(Windows)清空缓存重新请求Cache-Control: max-age=31536000, immutable
+ 带hash文件名Cache-Control: no-cache
+ 合理设置ETagCache-Control: no-store
缓存管理就像给网站做「物资调度」,合理使用能让加载速度提升数倍。
建议通过实际项目的瀑布流分析,观察哪些资源可以延长缓存时间,哪些需要严格控制实时性。记住:缓存不是洪水猛兽,用对了就是性能利器。