Nginx Gzip压缩:提升网站加载速度

启用Nginx Gzip压缩可缩小基于文本的响应,提升页面加载速度——涵盖安全设置、目标MIME类型、测试方法及CDN注意事项。

Nginx Gzip压缩:提升网站加载速度

Nginx Gzip压缩通过缩小基于文本的响应在网络传输前的体积,帮助您的网站加载更快。如果您的页面包含HTML、CSS、JavaScript、JSON、XML或SVG文件,压缩可以在不改变用户在浏览器中看到的内容的情况下,减少传输大小。

目标很简单:发送更少的字节,减少等待时间,更好地利用带宽。对于大多数生产环境站点,Gzip是最容易安全启用的Nginx性能优化之一。

Gzip压缩在Nginx中的工作原理

Gzip压缩发生在Nginx选择响应之后、发送响应给客户端之前。浏览器通过Accept-Encoding请求头表明支持压缩。如果Gzip已启用且响应类型与您的配置匹配,Nginx会压缩响应体并附带Content-Encoding: gzip发送。

这种方法对文本格式效果最佳,因为它们包含重复模式。HTML模板、CSS类名、JavaScript标识符和JSON键通常压缩效果很好。图片、视频、PDF和归档文件通常已经压缩过,尝试对它们进行gzip压缩可能会浪费CPU资源而不会显著减小文件体积。

基本配置通常放在http块中,以便应用于所有server块:

gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_vary on;
gzip_proxied any;
gzip_types
    text/plain
    text/css
    text/xml
    application/json
    application/javascript
    application/xml
    application/rss+xml
    image/svg+xml;

gzip on指令启用压缩。gzip_types告诉Nginx除了默认的text/html之外还要压缩哪些MIME类型。gzip_min_length避免在小型响应上浪费CPU,因为Gzip头部开销可能抵消压缩收益。

gzip_vary on添加Vary: Accept-Encoding头部。如果您的站点位于CDN或共享缓存后面,这一点很重要,因为缓存需要知道压缩和未压缩版本是同一URL的不同变体。

关于更广泛的Nginx性能基线,您可能还想查看Nginx性能调优

一个容易让人困惑的细节:当Gzip启用时,Nginx总是压缩text/html,因此text/html不需要出现在gzip_types中。如果您仍然添加它,Nginx可能会警告MIME类型重复。这个警告无害,但表明配置是复制过来而未清理的。

选择安全的压缩设置

Nginx Gzip压缩最大的错误是将压缩级别当作音量旋钮。并非越高越好。Gzip级别通常从19。级别1最快但压缩较少。级别9压缩更多但可能显著增加CPU开销。

对于许多网站,gzip_comp_level 456是实用范围。它在不使服务器过载的情况下提供良好的压缩。如果您的Nginx服务器处理高流量或运行在小型实例上,避免直接跳到级别9

良好的默认设置如下:

  • 使用gzip_comp_level 5实现平衡配置。
  • 使用gzip_min_length 1024让小型响应跳过压缩。
  • 压缩基于文本的资源,而非已压缩的媒体。
  • 当涉及缓存或CDN时保持gzip_vary on
  • 启用压缩后测试CPU使用情况。

这是一个常见场景。您运行一个包含许多CSS、JavaScript和HTML页面的文档站点。在Gzip之前,一个页面加载650 KB的文本资源。启用压缩后,传输大小可能大幅下降,而浏览器在解压后仍收到相同的文件。慢速连接的用户感受最明显。

收益并非在每个站点上都相等。以JPEG图片为主的页面不会因Gzip而改善太多。发送大型JSON响应的仪表盘可能会改善很多。

对于API,要更加谨慎。压缩像{"ok":true}这样的小型JSON响应通常毫无意义。压缩300 KB的搜索结果或报告负载则值得。如果您的API返回私有数据并在同一响应中反映用户控制的输入,请在启用压缩前与应用程序团队讨论压缩风险。这并不意味着“永远不要压缩API”。而是说压缩应与缓存、cookies和响应头一样纳入审查范围。

如何测试Gzip是否正常工作

更改Nginx配置后,在重新加载前测试语法:

nginx -t

然后通过服务管理器或部署流程重新加载Nginx。重新加载通常就足够了,因为这是配置更改,而非完整的二进制重启。

您可以使用curl检查响应:

curl -I -H "Accept-Encoding: gzip" https://example.com/app.css

查找此头部:

Content-Encoding: gzip

同时检查:

Vary: Accept-Encoding

如果未看到Content-Encoding: gzip,请验证响应MIME类型。例如,以text/plain提供的JavaScript文件如果包含text/plain仍可能压缩,但使用不常见内容类型的自定义API响应可能不匹配您的gzip_types列表。

浏览器开发者工具也有帮助。打开网络选项卡,重新加载页面,检查响应头部和传输大小。对于可压缩文件,传输大小应小于未压缩资源大小。

如果您还使用CDN,请记住CDN可能执行自己的压缩。在这种情况下,Nginx可能不是决定浏览器接收内容的最终层。尽可能测试直接源站访问和公共CDN URL。

如果直接源站响应已压缩但CDN响应未压缩,请检查CDN的压缩设置和缓存键行为。如果CDN响应已压缩但源站未压缩,那可能没问题。许多团队有意让CDN处理公共静态压缩,同时保持源站配置更简单。

何时谨慎使用Gzip

Gzip对大多数静态和动态内容都是安全的,但在某些情况下应放慢速度并仔细测试。

不要压缩已经压缩过的文件。常见示例包括:

  • .jpg.jpeg.png.webp
  • .mp4.mov和其他视频格式
  • .zip.gz.tar.gz和归档包
  • 大多数字体文件,取决于格式和交付路径

您还应监控CPU使用情况。压缩并非免费。如果您的服务器已经接近CPU限制,启用激进压缩可能会在负载下使响应时间更糟。从中等设置开始,然后监控流量、延迟和CPU。

安全敏感应用程序还应避免在压缩响应中暴露与攻击者控制输入相邻的秘密。这是一个更专业化的风险,但对于在包含令牌或私有数据的页面中反映用户输入的应用程序,值得了解。

对于静态资源,另一种选择是在构建管道中预压缩文件,并从磁盘提供.gz版本。这可以减少运行时CPU使用,特别是对于大型JavaScript包。动态API响应如果需要压缩,仍需要运行时压缩。

如果您提供预压缩文件,启用gzip_static on;并确保.gz文件与未压缩文件来自完全相同的资源版本。过时的app.js.gz旁边有更新的app.js是一个令人沮丧的bug:只有请求Gzip的客户端才会看到旧代码。

gzip_static on;

该指令适用于构建产物,而非动态上游响应。对于从应用服务器代理的动态响应,除非上游已发送压缩体,否则Nginx仍需要运行时压缩。

何时寻求帮助

如果启用Gzip导致高CPU、CDN行为不一致或对旧客户端响应异常,请咨询有经验的Nginx管理员或DevOps工程师。如果压缩设置分布在多个包含的配置文件中,且您不确定哪个块实际生效,也应寻求帮助。

对于简单网站,Gzip可以在几分钟内启用。对于高流量应用程序,将其视为任何性能更改:测试、逐步推出并监控结果。

Nginx Gzip压缩是提升文本密集型网站和API加载速度的实用方法。保持MIME类型集中,选择适中的压缩级别,并在重新加载后验证头部。一旦正常工作,用户将获得更小的响应,而您的应用程序代码保持不变。