你以为服务器只能靠带宽硬刚?不,压缩才是性能优化的王道!
一、什么是HTTP压缩?
HTTP压缩是Web服务器在响应内容前对数据进行压缩,浏览器收到后自动解压。这样可以大幅减少传输体积,加快页面加载速度,提升用户体验。常见压缩算法有gzip、deflate、br(Brotli)。
为什么要用HTTP压缩?
- 节省带宽 :压缩后体积更小,省钱省资源。
- 加速访问 :页面、脚本、样式表等文本资源加载更快。
- SEO友好 :谷歌等搜索引擎更青睐速度快的网站。
压缩的原理
- 浏览器发起请求时,通过 Accept-Encoding 头告诉服务器自己支持哪些压缩算法。
- 服务器判断资源类型和客户端支持,选择合适的压缩方式。
- 服务器用 Content-Encoding 头告知浏览器采用了哪种压缩。
- 浏览器自动解压,渲染页面。
二、Node.js 实现 HTTP 文件压缩
javascript
const http = require('http') // 引入Node.js内置HTTP模块
const path = require('path') // 引入路径处理模块
const fs = require('fs') // 引入文件系统模块
const mime = require('mime') // 引入mime类型识别模块
const zlib = require('zlib') // 引入zlib压缩模块
const server = http.createServer((req, res) => { // 创建HTTP服务器
let filePath = path.resolve(__dirname, path.join('www', req.url)) // 解析请求路径,定位静态文件
if (fs.existsSync(filePath)) { // 判断文件或目录是否存在
const stat = fs.statSync(filePath) // 获取文件或目录信息
if (stat.isDirectory()) { // 如果是目录
filePath = path.join(filePath, '/index.html') // 默认返回index.html
}
if (fs.existsSync(filePath)) { // 再次确认文件存在
const { ext } = path.parse(filePath) // 获取文件扩展名
const stat = fs.statSync(filePath) // 获取文件信息(用于缓存判断)
const timeStamp = req.headers['if-modified-since'] // 获取客户端缓存时间戳
let status = 200 // 默认状态码200
if (timeStamp && Number(timeStamp) === stat.mtimeMs) { // 如果客户端缓存未过期
status = 304 // 返回304,表示未修改
}
const mimeType = mime.getType(ext) // 获取文件MIME类型
const responseHeaders = {
'Content-Type': mimeType, // 设置响应类型
'Cache-Control': 'max-age=86400', // 设置强缓存一天
'Last-Modified': stat.mtimeMs, // 设置最后修改时间
}
const acceptEncoding = req.headers['accept-encoding'] || ' ' // 获取客户端支持的压缩方式
// 判断是否为文本/应用类型,只有这些类型才适合压缩
const compress = /^(text|application)\//.test(mimeType)
if (compress && acceptEncoding) { // 如果需要压缩且客户端支持
acceptEncoding.split(/\s*,\s*/).some((item) => { // 遍历支持的压缩方式
if (item === 'gzip') {
responseHeaders['Content-Encoding'] = 'gzip' // 优先使用gzip
return true
}
if (item === 'deflate') {
responseHeaders['Content-Encoding'] = 'deflate' // 其次使用deflate
return true
}
if (item === 'br') {
responseHeaders['Content-Encoding'] = 'br' // 支持Brotli
return true
}
return false // 未匹配则继续
})
}
res.writeHead(status, responseHeaders) // 写入响应头
const compressEncoding = responseHeaders['Content-Encoding'] // 获取最终压缩方式
if (status === 200) { // 只有200才返回内容
const fileStream = fs.createReadStream(filePath) // 创建文件读取流
if (compress && compressEncoding) { // 如果需要压缩
let comp = null
if (compressEncoding === 'gzip') {
comp = zlib.createGzip() // 创建gzip压缩流
} else if (compressEncoding === 'deflate') {
comp = zlib.createDeflate() // 创建deflate压缩流
} else if (compressEncoding === 'br') {
comp = zlib.createBrotliCompress() // 创建brotli压缩流
}
fileStream.pipe(comp).pipe(res) // 文件流->压缩流->响应
} else {
fileStream.pipe(res) // 不压缩直接输出
}
} else {
res.end() // 304直接结束响应
}
}
}
})
server.listen(3000, () => { // 启动服务器
console.log('server is running at http://localhost:3000') // 控制台输出服务地址
})
代码逐行讲解
zlib
模块是 Node.js 内置的压缩库,支持 gzip、deflate、brotli。- 通过
Accept-Encoding
判断客户端支持的压缩方式,优先选择 brotli > gzip > deflate。 - 只对文本和 application 类型的资源进行压缩,图片等二进制文件无需压缩。
- 设置
Content-Encoding
响应头,浏览器自动解压。
三、知识点深度讲解
1. Accept-Encoding 与 Content-Encoding
- Accept-Encoding :浏览器告诉服务器自己支持哪些压缩算法(如gzip, deflate, br)。
- Content-Encoding :服务器实际采用的压缩方式。
- 浏览器和服务器协商,优先选择双方都支持的算法。
2. 只压缩文本类资源的原因
- 文本(HTML、CSS、JS、JSON等)压缩率高,效果明显。
- 图片、音视频等二进制文件本身已压缩,再压缩收益极低甚至反而变大。
3. Node.js流式压缩的优势
- 利用pipe机制,边读边压缩边发送,内存占用低,效率高。
- 支持大文件和高并发场景。
4. 缓存与压缩的协同
- 配合 Cache-Control 和 Last-Modified ,可实现高效缓存+压缩,极大提升性能。
- 304响应时无需传输内容,进一步节省带宽。
5. 常见问题与优化建议
- CPU消耗 :压缩会增加服务器CPU负载,高并发场景建议静态压缩或用CDN。
- 兼容性 :IE6及以下不支持br,主流浏览器均支持gzip。
- 安全性 :避免对用户上传的未知文件类型进行压缩,防止攻击。
四、压缩与未压缩效果对比
1. 不进行压缩时的响应效果


如上图所示,未开启压缩时,响应头部没有 Content-Encoding
字段,响应体体积较大(vue.js 540KB),传输耗时也相对更长。
2. 启用压缩后的响应效果

如图,开启 gzip 压缩后,响应头部出现
Content-Encoding: gzip
,响应体体积大幅缩小(vue.js 129KB 没压缩前540KB),传输速度明显提升。
3. 对比分析
- 体积变化:压缩后文件体积通常可减少 60% 以上,尤其是文本类资源(HTML、CSS、JS)。
- 加载速度:压缩减小了网络传输的数据量,页面加载更快,用户体验更佳。
- 兼容性:主流浏览器均支持 gzip/br,压缩对终端用户透明。
- 服务器压力:压缩会增加服务器 CPU 占用,但带宽节省更为显著。
小结:HTTP 压缩是提升 Web 性能的利器,建议在 Node.js 服务中默认开启,尤其是面向公网的静态资源服务。
五、最佳实践总结
- 只压缩文本类资源,避免对图片等二进制文件压缩
- 配合合理缓存策略,提升整体性能
- 生产环境建议用成熟中间件(如compression)
- 监控服务器负载,合理分配资源 🚀 只需几行代码,让你的Node.js服务器"瘦身"飞起来,页面加载快到飞起!赶快试试吧!