强制缓存
强制缓存,只对引用的资源缓存
缺陷:无服务文件修改,可能还是走的缓存,不能即使获取最新文件
//30s
res.setHeader('Cache-Control', 'max-age=30');
//兼容低版本, 到什么时间结束
res.setHeader('Expires', new Date(Date.now() + 30 * 1000).toUTCString());
协商缓存
- no-cache: 缓存,但是每次会请求服务器
- no-store: 不缓存
缺点:
- 可能文件没变化,时间变化了
- 不够精准
- 可能CDN放置到服务器上的时间不一致
//获取文件修改时间
const ctime = stats.ctime.toUTCString();
//获取请求携带的最后修改时间
const ifModifiedSince = req.headers['if-modified-since'];
//如果请求携带的修改时间跟服务器文件的修改时间一直,走缓存
if (ctime === ifModifiedSince) {
res.statusCode = 304;
res.end();
} else {
//设置最后修改时间
res.setHeader('Last-Modified', ctime);
res.end();
}
指纹缓存(etag)
读文文件内容,产生
md5
戳,可以用md5
戳校验,但是读取文件时间长,一般需要产生一个相对简单的etag
const crypto = require('crypto')
//获取请求携带的etag
const reqEtag = req.headers['if-none-match'];
//根据文件生产一个指纹
const etag = cryto.createHash('md5').update(fs.readFileSync(filePath)).digest('base64');
//如果请求携带的指纹跟服务器的指纹相同,走缓存
if (reqEtag === etag) {
res.statusCode = 304;
res.end()
} else {
//设置etag
res.setHeader('Etag', etag);
res.setHeader('Content-Type', `${mime.getType(filePath)};charset=utf8`);
fs.createReadStream(filePath).pipe(res);
}