用Node静态服务器,掌握HTTP缓存

  |  

Node.js静态服务器

const fs = require('fs')
const http = require('http')
const mime = require('mime')
const path = require('path')
const url = require('url')
const crypto = require('crypto')
// 通过文件修改时间判断是否使用缓存资源
// Last-Modified(响应头中) / if-modified-since (请求头中)
// 存在的问题
/**
* 1、某些服务器不能精确到文件的最后修改时间, 这样就无法通过最后修改时间来判断是否使用缓存
* 2、某些文件的修改时间非常频繁,在秒下的时间内进行修改, last-modified只能精确到秒
* 3、一些文件的最后修改时间改了,但是内容没发生变化
* 4、如果同一样的文件位于多个CDN中,服务器上的内容虽然一样,但是修改时间不一样
*/

// 针对上面的问题, 引入 ETag(实体标签的缩写)(响应头中) / if-none-match (请求头中)

// gitee提示内容违规,先注释
// http.createServer(function(req,res){
// const {pathname} = url.parse(req.url, true)
// const filepath = path.join(__dirname,pathname)
// // fs.stat 获取文件信息
// fs.stat(filepath, (err, stat) => {
// if(err) {
// return sendError(req,res)
// } else { // 文件读取成功
// // 获取最后修改时间
// const ifModifiedSince = req.headers['if-modified-since'];
// const lastModified = stat.ctime.toGMTString()

// // 与 ETag对应的
// const ifNoneMatch = req.headers['if-none-match']
// // 怎么知道文件内容是否修改过? 计算文件hash

// // 方案一
// // 下面这两行代码需要优化, 如果文件 10G ,那么md5的计算量会比较大
// // const file = fs.readFileSync(filepath)
// // const Etag = crypto.createHash('md5').update(file).digest('hex')
// // if(lastModified === ifModifiedSince || ifNoneMatch === Etag) {
// // res.writeHead(304)
// // res.end()
// // } else {
// // return send(req,res, filepath, stat, Etag)
// // }

// // 方案二
// // 优化md5计算量
// // 每次读取64kb大小的文件, 不需要一次把10G读入内存
// 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')
// // 这里是命中其中一种协商缓存就返回304
// if(lastModified === ifModifiedSince || ifNoneMatch === Etag) {
// res.writeHead(304)
// res.end()
// } else {
// return send(req,res, filepath, stat, Etag)
// }
// })
// // 这里采用md5计算还是比较慢的,需要考虑其他更好的方案
// }
// })
// }).listen(8080)

function send(req,res, filepath, stat, etag) {
res.setHeader('Content-Type', mime.getType())
// 把最后修改时间发送给客户端之后,客户端会把此时间保存起来,下次再获取此资源时会把时间带回来
res.setHeader('Last-Modified', stat.ctime.toGMTString())

// Etag ,通过文件内容 + hash算法计算得来 crypto.createHash('md5').update(file).digest('hex')
res.setHeader('ETag', etag)
fs.createReadStream(filepath).pipe(res)
}

function sendError(req,res) {
res.end('Not Found')
}

// 强缓存, 这里就不演示这个了,相对比较简单
// res.setHeader('Cache-Control', "max-age=30")

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. Node.js静态服务器
,