通过http header 设置缓存
以 nodejs 做服务器举例:
// mime.js 按照文件后缀名来判断response的ContentType
exports.types = {
'jpg': 'image/jpeg',
'json': 'application/json'
}
// config.js 匹配到有缓存策略的文件,设置缓存时间
exports.Expires = {
fileMatch: /^(gif|png|jpg|js|css)/ig,
maxAge: 60 * 60 * 24 * 365 // 一年
}
一、 设置浏览器强缓存
使用Expires和Cache-Control实现浏览器的强缓存
// app.js 启动文件
var http = require('http')
var url = require('url')
var fs = require('fs')
var path = require('path')
var mime = require('./mime').types
var config = require('./config')
var PORT = 8000
var server = http.createServer(function (request, response) {
var pathname = url.parse(request.url).pathname // 获取文件名
var realPath = 'assets' + pathname // 获取文件的实际位置
var ext = path.extname(realPath) // 获取文件名后缀
ext = ext ? ext.slice(1) : 'unknown'
var contentType = mime[ext] || 'text/plain' // 根据文件名后缀来判断response的ContentType
if (ext.match(config.Expires.fileMatch)) { // 匹配到有缓存策略的文件
// 设置缓存策略
var expires = new Date() // 获取服务器当前时间
expires.setTime(expires.getTime() + config.Expires.maxAge * 1000) // 服务器当前时间加上缓存时间
response.setHeader('Expires', expires.toUTCString()) // 设置response的Expires的响应头
response.setHeader('Cache-Control', 'max-age=' + config.Expires.maxAge) // 设置response的Cache-Control的响应头
}
// 判断文件是否存在
fs.exists(realPath, function (exists) {
if (!exists) { // 文件不存在返回404
response.writeHead(404, {
'Content-Type': 'text/plain'
})
response.write('This request URL ' + pathname + 'was not found!')
response.end()
} else { // 文件存在,则用二进制的方式读取文件
fs.readFile(realPath, 'binary', function (err, file) {
if (err) { // 读取失败,则返回500
response.writeHead(500, {
'Content-Type': 'text/plain'
})
response.end()
} else { // 读取成功,则返回文件以及200的响应码
response.writeHead(200, {
'Content-Type': contentType
})
response.write(file, 'binary')
response.end()
}
})
}
})
})
server.listen(PORT)
console.log('Server running at port: ' + PORT)
二、设置浏览器弱缓存
使用Last-Modified实现浏览器的弱缓存
// app.js 启动文件
var http = require('http')
var PORT = 8000
var url = require('url')
var fs = require('fs')
var path = require('path')
var mime = require('./mime').types
var config = require('./config')
var server = http.createServer(function (request, response) {
var pathname = url.parse(request.url).pathname // 获取文件名
var realPath = 'assets' + pathname // 获取文件的实际位置
var ext = path.extname(realPath) // 获取文件名后缀
ext = ext ? ext.slice(1) : 'unknown'
var contentType = mime[ext] || 'text/plain' // 根据文件名后缀来判断response的ContentType
fs.stat(realPath, function (err, stat) {
var lastModified = stat.mtime.toUTCString() // 获取文件最后更新的时间
response.setHeader('Last-Modified', lastModified)
if (request.headers['if-modified-since'] && request.headers['if-modified-since'] === lastModified) { // 对比浏览器request header中的if-modified-since 和 文件最后更新时间,若一致,则不需要重新返回资源。
response.writeHead(304, 'Not Modified')
response.end()
} else {
fs.exists(realPath, function (exists) {
if (!exists) { // 文件不存在返回404
response.writeHead(404, {
'Content-Type': 'text/plain'
})
response.write('This request URL ' + pathname + 'was not found!')
response.end()
} else { // 文件存在,则用二进制的方式读取文件
fs.readFile(realPath, 'binary', function (err, file) {
if (err) { // 读取失败,则返回500
response.writeHead(500, {
'Content-Type': 'text/plain'
})
response.end()
} else { // 读取成功,则返回文件以及200的响应码
response.writeHead(200, {
'Content-Type': contentType
})
response.write(file, 'binary')
response.end()
}
})
}
})
}
})
})
server.listen(PORT)
console.log('Server running at port: ' + PORT)