【gzip】前端启用gzip压缩详解

136 阅读12分钟
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.gzgzip_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 ongzip 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. 快速验证步骤

image.png

  1. 检查响应头
    在浏览器开发者工具的 Network 面板中,确认响应头是否包含:

    Content-Encoding: gzip
    
  2. 直接请求 .gz 文件
    手动访问 https://your-domain.com/app.js.gz,若返回 404,说明文件未正确部署。

  3. 服务器日志检查
    查看 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文件,服务器做了什么处理?

image.png服务器在处理前端打包的.gz文件时,主要进行以下操作‌:

  1. 静态压缩‌:在构建过程中,使用 webpack** 或 Vite** 等工具预先生成对应的.gz文件。当浏览器请求某个资源(如xxx.js)时,服务器直接返回对应的xxx.js.gz文件,而不需要实时压缩,这样可以显著减少服务器的计算负担‌。
  2. 动态压缩‌:服务器通过内置的 gzip** 模块对请求的资源进行实时压缩,比如nginx。当浏览器请求某个文件时,服务器会对该文件进行gzip压缩后传输给浏览器。这种方式虽然可以实时压缩,但对服务器的CPU资源消耗较大,通常建议采用静态压缩的方式以减少服务器负担‌。
  3. 配置 Nginx ‌:在Nginx配置中,可以通过设置gzip on来开启gzip压缩功能,并配置压缩级别和类型。例如,可以设置gzip_comp_level 6来指定压缩级别为6,gzip_types text/plain application/javascript text/css application/xml text/javascript来指定压缩的文件类型‌。
  4. 浏览器支持‌:浏览器在请求资源时会自动在请求头中包含Accept-Encoding: gzip,表明支持gzip压缩。服务器在响应时,如果资源已经被压缩为.gz格式,则会在响应头中包含Content-Encoding: gzip,浏览器接收到压缩资源后会自动解压‌12。

1、服务器处理流程

  1. 客户端请求资源

    http
    GET /static/js/main.js HTTP/1.1
    Accept-Encoding: gzip, deflate
    
  2. 服务器检测 .gz 文件

    • 检查是否存在 main.js.gz(与请求的 main.js 同目录)
    • 若存在且客户端支持 gzip,直接返回 .gz 文件
    • 若不存在,实时压缩原始文件并返回(需要启用动态压缩)
  3. 返回响应

    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 // 保留原始文件
    })
  ]
};

四、注意

  1. 版本一致性

    • 确保 .gz 文件与原始文件版本严格同步
    • 部署时需同时上传原始文件和 .gz 文件
  2. 缓存控制

    nginx
    location ~* .(js|css|html)$ {
      add_header Cache-Control "public, max-age=31536000";
      add_header Vary Accept-Encoding;
    }
    
  3. Brotli 补充方案

    • 同时生成 .br 文件(Brotli 压缩)
    • Nginx 配置优先使用 Brotli:
    •     nginx
          brotli_static on;
          gzip_static on;
      
  4. CDN 兼容性

    • 检查 CDN 是否支持自动识别 .gz 文件
    • 部分 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 负载高低流量网站

验证方法

  1. 检查响应类型

    bash
    # 请求时声明支持 gzip
    curl -I -H "Accept-Encoding: gzip" https://example.com/static/js/main.js
    
    # 预期响应头
    HTTP/2 200
    Content-Encoding: gzip
    Vary: Accept-Encoding
    
  2. 强制请求未压缩内容

    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 11gzip, deflate不支持 Brotli

二、核心工作机制

  1. 请求阶段

    http
    GET /static/js/main.js HTTP/1.1
    Host: example.com
    Accept-Encoding: gzip, deflate, br
    
  2. 服务器响应逻辑

    • 若服务器支持压缩,返回压缩内容并添加 Content-Encoding 头
    • 若不支持/禁用压缩,返回原始内容
    http
    HTTP/1.1 200 OK
    Content-Encoding: gzip
    Content-Type: application/javascript
    Vary: Accept-Encoding
    
  3. 浏览器解压流程

    • 根据 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";
}

通过这种自动协商机制,浏览器与服务端无需人工干预即可实现最佳压缩策略。开发者只需确保:

  1. 服务器正确配置压缩功能
  2. 静态资源预压缩文件存在
  3. 缓存策略包含 Vary: Accept-Encoding

相关资料

juejin.cn/post/750963… blog.csdn.net/weixin_4411…