本文主要是介绍实际操作理解 HTTP 缓存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
实际操作理解 HTTP 缓存
网上很多优秀的文章介绍了 HTTP 缓存,但大多是文字内容。
最好结合实际操作,方便更好的理解。
实际操作就需要开启一个 HTTP 服务测试 HTTP 协议,建议使用原生的 Node.js 的 http 模块。
不建议使用 Express Koa Egg 等开发框架,因为它们内置了很多功能,不利于学习原生的 API。
开启 HTTP 服务
创建 app.js
// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {res.end('Hello World!')
})server.listen(3000, () => {console.log('running http://localhost:3000')
})
运行:
# 建议使用 nodemon 运行
# npm i -g nodemon
nodemon ./app.js
访问:http://localhost:3000
输出 HTML 内容
// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {res.end(`
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1></body>
</html>
`)
})server.listen(3000, () => {console.log('running http://localhost:3000')
})
输出 html 文件内容
创建 index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1><p>index.html</p></body>
</html>
修改 app.js
// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 每次请求今来都要重新读取该文件const data = fs.readFileSync('./index.html')res.end(data)
})server.listen(3000, () => {console.log('running http://localhost:3000')
})
现在每次请求进来,都要读取磁盘文件 index.html
。
磁盘读取速度,网络速度都会影响响应的速度。
划分请求路径
此时所有路径的请求都返回同样的 html 内容。
这解释了,请求路径只是一个标识,需要返回什么内容,是服务器处理的。
创建 main.js
console.log('this is main.js')
添加 main.js 引入
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><title>Document</title></head><body><h1>HTTP 缓存</h1><p>index.html</p><script src="./main.js"></script></body>
</html>
修改 app.js
// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')
const url = require('url')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})server.listen(3000, () => {console.log('running http://localhost:3000')
})
缓存针对的是 GET 请求
缓存一般针对的是静态资源,html css js img 等。
缓存针对的是 GET 请求。
缓存操作目标 - MDN
虽然 HTTP 缓存不是必须的,但重用缓存的资源通常是必要的。然而常见的 HTTP 缓存只能存储
GET
响应,对于其他类型的响应则无能为力。
打印请求日志
查看服务器是否接受了请求,可以确认资源是否使用了缓存。
为请求添加日志打印:
// 使用 nodejs 开启一个 HTTP 服务
const http = require('http')
const fs = require('fs')
const url = require('url')const server = http.createServer()// 任何请求今来,就会触发 request 请求事件,执行处理函数
server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})server.listen(3000, () => {console.log('running http://localhost:3000')
})
再次访问页面,观察控制台,可以看到每次请求都打印了日志。
设置缓存
缓存控制 - MDN
通过定义响应头的 Cache-Control
来设置缓存。
http 模块有两个设置响应头的方法:
// 一次设置一个字段
request.setHeader(name, value)
// 一次可以设置多个字段
request.writeHead(statusCode, {name: value,name: value
})
server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')// 设置不缓存res.setHeader('Cache-Control', 'no-store')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})
查看浏览器的请求日志,可以看到设置的请求头信息。
设置缓存过期时间
过期机制中,最重要的指令是 “
max-age=<seconds>
”,表示资源能够被缓存(保持新鲜)的最大时间。相对Expires而言,max-age是距离请求发起的时间的秒数。针对应用中那些不会改变的文件,通常可以手动设置一定的时长以保证缓存有效,例如图片、css、js等静态资源。
server.on('request', (req, res) => {// 打印请求日志console.log(`${req.method} ${req.url}`)// 如果请求 /,则返回 index.html// 如果请求 /main.js,则返回 main.jsconst { pathname: path } = url.parse(req.url)if (path === '/') {const data = fs.readFileSync('./index.html')res.end(data)} else if (path === '/main.js') {const data = fs.readFileSync('./main.js')// 缓存20秒res.setHeader('Cache-Control', 'max-age=20')res.end(data)} else {// 不再受理范围之内的,统一返回 404res.statusCode = 404res.end()}
})
再次访问页面,注意要关闭浏览器的 禁用缓存 (Disable cache)。
查看控制台,发现 main.js
的请求日志没有打印,表示浏览器使用了缓存。
浏览器请求日志中也会显示 (memory cache)
表示缓存在内存中,假如内容很大,也可能会缓存在磁盘中。
关于 HTTP 缓存可以参考:
一文读懂http缓存(超详细)
HTTP 缓存 - MDN
这篇关于实际操作理解 HTTP 缓存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!