避免web页面编写缓存代码
axios-cache-interceptor虽然能实现响应缓存,但不支持只缓存特定请求。也会出现一个请求修改数据;缓存没有失效,显示的页面出错。axios-cache-interceptor提供手动失效缓存,来解决这个问题。这样反而让代码更加复杂且难以维护。
HTTP的缓存机制
HTTP1.1, Cache-Control 标头控制浏览器缓存。
Cache-Control: max-age=604800
HTTP1.0,Expires指定实际的过期时间。
Expires: Tue, 28 Feb 2022 22:22:22 GMT
验证响应
过时的响应不会立即被丢弃。HTTP 有一种机制,可以通过询问源服务器将陈旧的响应转换为新的响应。这称为验证,有时也称为重新验证。
验证是通过使用包含 If-Modified-Since 或 If-None-Match 请求标头的条件请求完成的。
Last-Modified/If-Modified-Since
下面是服务端返回的响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT
Cache-Control: max-age=3600
<!doctype html>
…
浏览器发送的请求
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2022 22:00:00 GMT
通常If-Modified-Since和Last-Modified搭配使用。If-Modified-Since和Last-Modified一样,返回304状态码,表示响应没有变化,可以继续在1小时内使用缓存。
ETag/If-None-Match
ETag 响应标头的值是服务器生成的任意值。服务器对于生成值没有任何限制,因此服务器可以根据他们选择的任何方式自由设置值——例如主体内容的哈希或版本号。
下面是服务端返回的响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "deadbeef"
Cache-Control: max-age=3600
<!doctype html>
…
下面是浏览器发送的请求
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "deadbeef"
ETag和If-None-Match一样,返回304状态码,表示响应没有变化,可以继续在1小时内使用缓存。
强制重新验证
如果想实时获取最新响应,可以使用no-cache强制验证。每次都发送请求询问响应是否发送变化。
HTTP1.1
Cache-Control: no-cache
HTTP1.0
Cache-Control: max-age=0, must-revalidate
实际使用
HTTP服务默认对静态资源做缓存处理,对API接口不做缓存。通常会有一些API接口不会经常修改数据,而且返回的数据又特别的大。可以使用HTTP的缓存机制避免传输大量数据,使用强制重新验证,确保浏览器实时获取最新响应。
以下是NodeJs的简单实现。
import Koa from 'koa'
import koaBody from 'koa-body'
import Router from '@koa/router'
const app = new Koa()
app.use(koaBody())
const router = new Router()
const now = new Date()
router.get('/test', (ctx, next) => {
const lastModified = now.toUTCString()
ctx.set('cache-control', 'no-cache')
ctx.set('last-modified', lastModified)
if (ctx.header['if-modified-since'] == lastModified) {
ctx.status = 304
} else {
ctx.status = 200
ctx.body = 'hello world'
}
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(8080)
返回304响应,表示缓存的响应没有被修改。浏览器根据Cache-Control: no-cache,自动缓存响应。每次都会重新验证缓存响应是否修改。自动发送If-Modified-Since。这些内容浏览器都自动完成,无需编写任何缓存代码
使用缓存的响应。
参考资料
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Caching