一、浏览器缓存机制
1、LastModified
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mime = require('mime')
http.createServer(function (req, res) {
const {pathname} = url.parse(req.url, true)
const filepath = path.join(__dirname, pathname)
fs.stat(filepath, (err, stats) => {
if (err) {
return sendError(req, res)
} else {
const ifModifiedSince = req.headers['if-modified-since']
const LastModified = stats.ctime.toGMTString()
if (ifModifiedSince === LastModified) {
res.writeHead(304)
res.end('')
} else {
return send(req, res, filepath, stats)
}
}
})
}).listen(8080)
function sendError(req, res) {
res.end('Not Found')
}
function send(req, res, filepath, stats) {
res.setHeader('Content-Type', mime.getType(filepath))
res.setHeader('Last-Modified', stats.ctime.toGMTString())
fs.createReadStream(filepath).pipe(res)
}
2、ETag
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mime = require('mime')
const crypto = require('crypto')
http.createServer(function (req, res) {
const {pathname} = url.parse(req.url, true)
const filepath = path.join(__dirname, pathname)
fs.stat(filepath, (err, stats) => {
if (err) {
return sendError(req, res)
} else {
const ifNoneMatch = req.headers['if-none-match']
const out = fs.createReadStream(filepath)
const md5 = crypto.createHash('md5');
out.on('data', function (data) {
md5.update(data)
})
out.on('end', function () {
const etag = md5.digest('hex')
if (ifNoneMatch === etag) {
res.writeHead(304)
res.end('')
} else {
return send(req, res, filepath, etag)
}
})
}
})
}).listen(8080)
function sendError(req, res) {
res.end('Not Found')
}
function send(req, res, filepath, etag) {
res.setHeader('Content-Type', mime.getType(filepath))
res.setHeader('ETag', etag)
fs.createReadStream(filepath).pipe(res)
}
3、expires
const http = require('http')
const url = require('url')
const path = require('path')
const fs = require('fs')
const mime = require('mime')
http.createServer(function (req, res) {
const {pathname} = url.parse(req.url, true)
const filepath = path.join(__dirname, pathname)
console.log(filepath)
fs.stat(filepath, (err, stats) => {
if (err) {
return sendError(req, res)
} else {
return send(req, res, filepath)
}
})
}).listen(8080)
function sendError(req, res) {
res.end('Not Found')
}
function send(req, res, filepath) {
res.setHeader('Content-Type', mime.getType(filepath))
// http1.0使用,已弃用
// res.setHeader('Expires', new Date(Date.now() + 30 * 1000).toUTCString())
// http1.1使用,优先级高于Expires
res.setHeader('Cache-Control', 'max-age=30')
/**
* 1、private:客户端可以缓存
* 2、public:客户端和代理服务器都可以缓存
* 3、max-age=60:缓存内容将在60秒后失效
* 4、no-cache:需要使用对比缓存验证数据,强制向源服务器再次验证
* 5、no-store:所有内容都不会缓存,强制缓存和对比缓存都不会触发
*/
res.setHeader('Cache-Control', 'max-age=30')
fs.createReadStream(filepath).pipe(res)
}