nginx:
gzip on;
gzip_static on;
gzip_proxied any;
gzip_min_length 1k;
gzip_buffers 4 16k;
# 开启 brotli压缩
# 需要安装对应的nginx模块,具体安装方式可以自行查询
# 可以与gzip共存不会冲突
brotli on;
brotli_comp_level 6;
brotli_buffers 16 8k;
brotli_min_length 20;
brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml;
一、配置压缩
为什么要用gzip压缩静态资源?是为了达到降低网络带宽,加快页面加载速度,但注意是基于css,js的原始文件进行zip压缩!这才是gzip使用的场景,当然,nginx也能实施压缩,就是在服务器端压缩浏览器解压缩,但是这样有点消耗服务器性能。。
有人说:压缩后css,js文件的原始文件不能删除,要跟gz文件一起共存,这样nginx gzip才能起作用! 如果是这样的话,webpack干嘛压缩成gz格式,直接给你nginx原始文件不就完了吗!
实际上,只要在对应作用域(http / server / location)开启了 gzip_static on,Nginx 就会在收到对 app.js 的请求时自动尝试查找同路径下的 app.js.gz。gzip_types 控制的是动态压缩需要压缩的 MIME 类型,与是否查找 .gz 文件无关,因此无需为每一种资源单独写 location。只有在需要精细化控制时,才需要在特定 location 中单独开启或关闭 gzip_static。
如果前端打包生成了 .gz 文件但浏览器请求到的文件格式未压缩(即未返回 Content-Encoding: gzip),通常是由以下 关键问题 导致的:
1. 服务器未启用静态压缩(未识别 .gz 文件)
原因:
- 服务器未配置
gzip_static on,导致无法优先返回预生成的.gz文件。 - 即使存在
.js.gz/.css.gz文件,服务器仍会返回原始文件或动态压缩。
解决方案:
在 Nginx 中明确启用静态压缩:
nginx
location / {
# 优先使用预生成的 .gz 文件
gzip_static on;
}
2. 文件路径或命名错误
原因:
.gz文件未与原始文件放在同一目录下。.gz文件名不匹配(例如原文件是app.js,但生成的是app.123456.js.gz)。
验证方法:
检查服务器上文件路径是否满足以下结构:
├── dist
│ ├── app.js
│ ├── app.js.gz 👈 必须同名且同目录
│ ├── style.css
│ └── style.css.gz
3. 浏览器请求头缺失 Accept-Encoding: gzip
原因:
- 浏览器未在请求头中携带
Accept-Encoding: gzip(罕见,现代浏览器默认支持)。 - 可通过开发者工具的 Network 面板检查请求头。
验证示例:
http
GET /app.js HTTP/1.1
Accept-Encoding: gzip, deflate, br 👈 必须包含 gzip
4. 动态压缩与静态压缩的协同
说明:
gzip_static on与gzip on可以并存,Nginx 会先查找是否存在.gz文件;若不存在,再依据gzip_types做动态压缩。- 需要确保 Nginx 编译时包含
http_gzip_static_module模块,并正确部署同名.gz文件。无需额外的“优先级配置”。
推荐配置:
nginx
gzip_static on; # 优先静态压缩
gzip on; # 动态压缩兜底(仅当无 .gz 文件时触发)
gzip_types text/css application/javascript application/json text/html;
5. 缓存问题
原因:
- 浏览器或 CDN 缓存了未压缩的旧版本文件。
- 服务器未正确设置
Vary: Accept-Encoding响应头,导致缓存混乱。
解决方案:
-
强制刷新浏览器缓存(
Ctrl + Shift + R)。 -
在 Nginx 中添加响应头:
nginx add_header Vary Accept-Encoding;
6. 快速验证步骤
-
检查响应头
在浏览器开发者工具的 Network 面板中,确认响应头是否包含:Content-Encoding: gzip -
直接请求
.gz文件
手动访问https://your-domain.com/app.js.gz,若返回 404,说明文件未正确部署。 -
服务器日志检查
查看 Nginx 日志,确认是否返回了.gz文件:bash tail -f /var/log/nginx/access.log
7. 配置示例(Nginx)
nginx
server {
listen 80;
root /path/to/dist;
location / {
# 关键配置:优先使用预生成的 .gz 文件
gzip_static on;
# 兜底动态压缩(可选)
gzip on;
gzip_types text/css application/javascript;
# 缓存控制
add_header Vary Accept-Encoding;
}
}
二、前端打包的 .gz文件,服务器做了什么处理?
服务器在处理前端打包的.gz文件时,主要进行以下操作:
- 静态压缩:在构建过程中,使用 webpack** 或 Vite** 等工具预先生成对应的.gz文件。当浏览器请求某个资源(如xxx.js)时,服务器直接返回对应的xxx.js.gz文件,而不需要实时压缩,这样可以显著减少服务器的计算负担。
- 动态压缩:服务器通过内置的 gzip** 模块对请求的资源进行实时压缩,比如nginx。当浏览器请求某个文件时,服务器会对该文件进行gzip压缩后传输给浏览器。这种方式虽然可以实时压缩,但对服务器的CPU资源消耗较大,通常建议采用静态压缩的方式以减少服务器负担。
- 配置 Nginx :在Nginx配置中,可以通过设置
gzip on来开启gzip压缩功能,并配置压缩级别和类型。例如,可以设置gzip_comp_level 6来指定压缩级别为6,gzip_types text/plain application/javascript text/css application/xml text/javascript来指定压缩的文件类型。 - 浏览器支持:浏览器在请求资源时会自动在请求头中包含
Accept-Encoding: gzip,表明支持gzip压缩。服务器在响应时,如果资源已经被压缩为.gz格式,则会在响应头中包含Content-Encoding: gzip,浏览器接收到压缩资源后会自动解压12。
1、服务器处理流程
-
客户端请求资源
http GET /static/js/main.js HTTP/1.1 Accept-Encoding: gzip, deflate -
服务器检测
.gz文件- 检查是否存在
main.js.gz(与请求的main.js同目录) - 若存在且客户端支持
gzip,直接返回.gz文件 - 若不存在,实时压缩原始文件并返回(需要启用动态压缩)
- 检查是否存在
-
返回响应
http HTTP/1.1 200 OK Content-Encoding: gzip Content-Type: application/javascript Vary: Accept-Encoding
2. 关键服务器配置
nginx
http {
# 开启静态 gzip 处理(优先使用预压缩文件)
gzip_static on;
# 动态压缩配置(后备方案)
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# 其他缓存和压缩参数
gzip_proxied any;
gzip_min_length 1k;
gzip_comp_level 6;
}
3. 配置解析
| 指令 | 作用 |
|---|---|
gzip_static on | 优先使用预生成的 .gz 文件,避免实时压缩的 CPU 消耗 |
gzip on | 启用动态压缩(当预压缩文件不存在时回退) |
gzip_types | 指定需要动态压缩的 MIME 类型 |
gzip_proxied any | 对所有代理请求启用压缩 |
gzip_min_length 1k | 仅压缩大于 1KB 的内容 |
4. 预压缩与实时压缩对比
| 特性 | 预压缩(.gz 文件) | 实时压缩 |
|---|---|---|
| CPU 消耗 | 无(直接读取文件) | 高(每次请求实时压缩) |
| 响应速度 | 快(无需计算) | 较慢(依赖 CPU 性能) |
| 适用场景 | 生产环境 | 开发环境或动态内容 |
| 文件管理 | 需维护 .gz 文件版本 | 无需额外文件 |
| 缓存友好性 | 高(内容不变 ETag 稳定) | 中(依赖服务器缓存策略) |
5. 验证方法
-
检查响应头
bash curl -I -H "Accept-Encoding: gzip" http://example.com/static/js/main.js确认返回以下头部:
http Content-Encoding: gzip Vary: Accept-Encoding -
文件大小对比
bash # 原始文件 ls -lh main.js # 显示 200KB # 压缩文件 ls -lh main.js.gz # 显示 50KB -
Nginx 日志分析
nginx # 在日志格式中添加 $gzip_ratio log_format compression '$remote_addr - $gzip_ratio';- 若比率为
1.00,表示未压缩 - 若比率类似
4.00,表示压缩率 4:1
- 若比率为
三、前端构建配置示例
Webpack(使用 compression-webpack-plugin)
// webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
plugins: [
new CompressionPlugin({
filename: '[path][base].gz', // 生成路径保持原结构
algorithm: 'gzip',
test: /.(js|css|html|svg)$/,
threshold: 10240, // 仅压缩 >10KB 文件
minRatio: 0.8, // 压缩率需优于 80%
})
]
};
Vite(使用 vite-plugin-compression)
javascript
// vite.config.js
import viteCompression from 'vite-plugin-compression';
export default {
plugins: [
viteCompression({
ext: '.gz', // 压缩扩展名
algorithm: 'gzip', // 可选 brotliCompress
threshold: 10240, // 仅压缩 >10KB 文件
deleteOriginFile: false // 保留原始文件
})
]
};
四、注意
-
版本一致性
- 确保
.gz文件与原始文件版本严格同步 - 部署时需同时上传原始文件和
.gz文件
- 确保
-
缓存控制
nginx location ~* .(js|css|html)$ { add_header Cache-Control "public, max-age=31536000"; add_header Vary Accept-Encoding; } -
Brotli 补充方案
- 同时生成
.br文件(Brotli 压缩) - Nginx 配置优先使用 Brotli:
-
nginx brotli_static on; gzip_static on;
- 同时生成
-
CDN 兼容性
- 检查 CDN 是否支持自动识别
.gz文件 - 部分 CDN 需要显式配置压缩策略
- 检查 CDN 是否支持自动识别
通过预生成 .gz 文件并合理配置服务器,可在不增加服务器 CPU 负载的前提下,显著提升静态资源传输效率(通常可减少 60-80% 的传输体积)。这种优化对高并发场景尤其重要。
在前端部署时是否需要同时保留原始文件和 .gz 压缩文件,取决于服务器配置。以下是具体场景分析及建议
五、 前端打包压缩文件部署时, 需要把压缩前的文件和压缩后的gz文件一块部署上去?
必须同时部署的情况
当服务器配置了 预压缩优先策略(如 Nginx 的 gzip_static)时:
1. 服务器配置示例(Nginx)
nginx
http {
gzip_static on; # 优先使用预生成的 .gz 文件
gzip on; # 启用动态压缩(后备方案)
}
2. 需要同时部署的原因
- 客户端兼容性:当客户端不支持
gzip时(如某些旧版浏览器),服务器自动回退到原始文件 - 请求头控制:若客户端请求头未包含
Accept-Encoding: gzip,返回未压缩文件 - 版本一致性:确保
.gz文件与原始文件版本严格同步(避免 CDN 缓存新旧版本混杂)
3. 文件结构示例
/static/
├─ js/
│ ├─ main.js # 原始文件(必须存在)
│ └─ main.js.gz # 压缩文件(必须存在)
├─ css/
│ ├─ style.css
│ └─ style.css.gz
可仅部署压缩文件的情况
当服务器 强制所有客户端使用压缩内容 时(需谨慎):
1. 实现方式
nginx
server {
location ~ \.js$ {
# 强制返回 .gz 文件(无论客户端是否支持)
try_files $uri.gz =404;
add_header Content-Encoding gzip always;
add_header Vary Accept-Encoding;
default_type application/javascript;
}
}
由于
.gz扩展会让 Nginx 判定为application/gzip,因此需要在不同资源类型上单独配置default_type(或拆分多个location),否则会导致浏览器收到错误的Content-Type。
2. 风险提示
- 客户端兼容性问题:部分旧版浏览器无法解压
.gz文件,导致页面空白 - SEO 影响:搜索引擎爬虫可能无法解析强制压缩的内容
- 调试困难:开发工具中无法直接查看原始代码
最佳实践方案
1. 通用部署策略
| 文件类型 | 是否部署 | 作用场景 |
|---|---|---|
| 原始文件 | ✅ 是 | 兼容不支持压缩的客户端、调试环境、CDN 回源 |
.gz 压缩文件 | ✅ 是 | 服务主流现代浏览器,减少传输体积 |
.br (Brotli) | 可选 | 进一步优化压缩率(需服务端支持 Brotli) |
2. 自动化部署示例(Webpack + CI/CD)
yaml
# GitLab CI 示例
deploy:
stage: deploy
script:
- npm run build
- find dist -type f -exec gzip -k {} ; # 生成 .gz 文件(保留原始文件)
- rsync -avz dist/ user@server:/var/www/html/
3. 文件清理策略
-
保留原始文件:始终保留原始文件以确保兼容性
-
定期清理旧版本:结合 CDN 缓存策略,清理超过 3 个历史版本的压缩文件
bash # 清理 7 天前的旧压缩文件 find /var/www/html -name "*.gz" -mtime +7 -exec rm {} ;
性能与存储权衡
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
原始 + .gz | 最佳兼容性,无性能损失 | 存储空间增加约 20% | 通用生产环境 |
仅 .gz | 节省存储空间 | 兼容性风险,需额外配置 | 内部系统/现代浏览器专用 |
| 仅原始 + 动态压缩 | 部署简单 | 服务器 CPU 负载高 | 低流量网站 |
验证方法
-
检查响应类型
bash # 请求时声明支持 gzip curl -I -H "Accept-Encoding: gzip" https://example.com/static/js/main.js # 预期响应头 HTTP/2 200 Content-Encoding: gzip Vary: Accept-Encoding -
强制请求未压缩内容
bash # 不携带压缩头 curl -I https://example.com/static/js/main.js # 预期响应头 HTTP/2 200 Content-Type: application/javascript
建议
- 生产环境:始终同时部署原始文件 +
.gz文件,兼顾性能和兼容性 - 存储敏感场景:可评估用户浏览器分布,若 100% 为现代浏览器可考虑仅用
.gz - 自动化处理:通过构建工具(Webpack/Vite)和 CI/CD 流水线自动生成并同步压缩文件
六、 浏览器请求资源时会自动携带请求头 Accept-Encoding ?
是的,现代浏览器在发送 HTTP 请求时会自动携带 Accept-Encoding 请求头。这是浏览器与服务器协商内容压缩方式的标准化机制,具体行为如下:
一、浏览器的默认行为
| 浏览器 | 典型值 | 说明 |
|---|---|---|
| Chrome 120+ | gzip, deflate, br | 默认支持 Brotli (br) |
| Firefox 115+ | gzip, deflate, br | |
| Safari 16+ | gzip, deflate, br | |
| Edge 120+ | gzip, deflate, br | |
| IE 11 | gzip, deflate | 不支持 Brotli |
二、核心工作机制
-
请求阶段
http GET /static/js/main.js HTTP/1.1 Host: example.com Accept-Encoding: gzip, deflate, br -
服务器响应逻辑:
- 若服务器支持压缩,返回压缩内容并添加
Content-Encoding头 - 若不支持/禁用压缩,返回原始内容
http HTTP/1.1 200 OK Content-Encoding: gzip Content-Type: application/javascript Vary: Accept-Encoding - 若服务器支持压缩,返回压缩内容并添加
-
浏览器解压流程:
- 根据
Content-Encoding自动选择解压器 - 流式解压(边下载边解压)
- 将解压后的内容交给渲染引擎
- 根据
三、关键点
1. 缓存与 Vary 头
服务器必须返回 Vary: Accept-Encoding,否则可能导致:
- 缓存污染(压缩/未压缩内容混存)
- 客户端收到错误的内容类型
2. 强制禁用压缩(调试场景)
-
浏览器扩展:使用 ModHeader 等工具删除
Accept-Encoding -
命令:
bash curl -H "Accept-Encoding: " http://example.com/resource
3. 性能优化建议
-
预压缩静态资源:在构建时生成
.gz/.br文件nginx # Nginx 配置示例 gzip_static on; brotli_static on; -
压缩阈值控制:避免压缩小文件(<1KB)
nginx gzip_min_length 1k;
4. 浏览器兼容性处理
浏览器端没有公开 API 可以直接判断某个压缩算法是否受支持,通常只能通过用户代理统计或服务端响应头(如 Content-Encoding: br)进行间接推断。最可靠的做法仍然是依赖内容协商机制,而不是在客户端做能力假设。
四、不同场景下的行为差异
| 请求类型 | 是否携带 Accept-Encoding | 说明 |
|---|---|---|
| HTML 页面请求 | ✅ 是 | |
| CSS/JS 资源请求 | ✅ 是 | |
| 图片/字体文件请求 | ✅ 是 | 但服务器通常不压缩二进制文件 |
| WebSocket 连接 | ❌ 否 | 需手动添加 |
| Fetch API 请求 | ✅ 默认携带 | 浏览器端无法修改该请求头 |
| XHR 请求 | ✅ 默认携带 |
五、开发者控制方案
1. 浏览器端的限制
Accept-Encoding属于受保护请求头,浏览器中的 Fetch/XHR/axios 等 API 无法自定义或删除该头部。- 若需要验证未压缩响应,可使用浏览器扩展、代理工具或命令行(如
curl -H "Accept-Encoding: identity")模拟请求。
2. 非浏览器客户端的灵活性
在服务端或原生应用中,可以手动设置 Accept-Encoding 用于调试或与第三方服务协商压缩算法。例如(Node.js 环境):
javascript
import fetch from 'node-fetch';
const resp = await fetch('https://example.com/api', {
headers: { 'Accept-Encoding': 'identity' }
});
六、服务器配置建议
nginx
http {
# 动态压缩配置
gzip on;
gzip_types text/html text/css application/json;
# 预压缩优先
gzip_static on;
brotli_static on;
# 缓存控制
add_header Vary Accept-Encoding;
# 排除不需要压缩的类型
gzip_disable "msie6";
}
通过这种自动协商机制,浏览器与服务端无需人工干预即可实现最佳压缩策略。开发者只需确保:
- 服务器正确配置压缩功能
- 静态资源预压缩文件存在
- 缓存策略包含
Vary: Accept-Encoding