网站加载速度直接影响用户体验和搜索引擎排名。在搬瓦工 VPS 上,通过 Nginx 开启 Gzip 压缩和浏览器缓存,往往能在不增加任何硬件成本的情况下让页面加载速度提升 40%–70%。本文详细说明两项配置的原理、参数含义与验证方法。

本文要点

  • Gzip 压缩的工作原理与适合压缩的 MIME 类型
  • Nginx gzip 相关指令的含义与推荐值
  • 浏览器缓存(expires / Cache-Control)配置
  • 静态文件缓存策略与版本化更新
  • 用命令和开发者工具验证配置是否生效

Gzip 压缩

原理

Nginx 在把响应发给客户端前,先用 Gzip 算法压缩文本内容,客户端收到后解压再渲染。文本文件(HTML、CSS、JS)压缩率通常达 70% 以上,大幅减少传输字节数,对移动端和海外访客效果尤其明显。

配置示例

# 放在 nginx.conf 的 http 块中
gzip on;
gzip_comp_level 6;          # 压缩级别 1-9,6 是速度与压缩率的平衡点
gzip_min_length 1024;       # 小于 1KB 的响应不压缩(收益微弱)
gzip_vary on;               # 添加 Vary: Accept-Encoding 头,兼容代理
gzip_proxied any;           # 对代理请求也压缩
gzip_buffers 16 8k;
gzip_types
    text/plain
    text/css
    text/javascript
    application/javascript
    application/json
    application/xml
    application/rss+xml
    image/svg+xml;

不要压缩已压缩格式

JPEG、PNG、GIF、WebP、MP4、zip 等文件本身已压缩,对它们再 Gzip 不仅无效,反而会浪费 CPU。在 gzip_types 里只列文本类 MIME 类型。

浏览器缓存(静态资源缓存)

原理

通过在响应头里设置 Cache-ControlExpires,告诉浏览器"这个文件在多久内不需要重新请求,直接用缓存"。对于不常变化的静态资源(图片、字体、CSS、JS),缓存时间设长,可大幅减少重复请求。

配置示例

server {
    # ...其他配置...

    # 静态文件长缓存
    location ~* \.(jpg|jpeg|png|gif|webp|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~* \.(css|js)$ {
        expires 7d;
        add_header Cache-Control "public";
    }

    location ~* \.(woff|woff2|ttf|eot)$ {
        expires 365d;
        add_header Cache-Control "public, immutable";
    }

    # HTML 不缓存或短缓存(保证用户拿到最新内容)
    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache";
    }
}

缓存时长参考

资源类型建议 expiresCache-Control 补充
HTML-1 或 no-cacheno-cache(动态内容)
CSS / JS(带版本号)1 年(365d)immutable
CSS / JS(无版本号)7 天public
图片 / 字体30–365 天public, immutable
API 响应不缓存no-store

版本化文件名是长缓存的前提

CSS/JS 设置长缓存时,更新文件后文件名或查询参数必须变化(如 app.v2.css),否则浏览器不会拉取新文件。构建工具(Webpack、Vite)默认带内容哈希,符合此要求。

Nginx 缓存层(proxy_cache)

若使用反向代理,还可以开启 proxy_cache 在 Nginx 层缓存后端响应,进一步减少后端压力。但对于简单静态站点,浏览器缓存已足够,proxy_cache 主要用于代理动态内容场景。

验证配置是否生效

验证 Gzip

# --compressed 让 curl 发送 Accept-Encoding: gzip
curl -I --compressed https://example.com
# 响应头应有:Content-Encoding: gzip

# 对比压缩前后体积
curl -s https://example.com | wc -c
curl -s --compressed https://example.com | wc -c

验证缓存头

curl -I https://example.com/style.css
# 应看到:
# Cache-Control: public
# Expires: ...(未来日期)

也可用浏览器开发者工具

在 Chrome DevTools → Network 面板中,点击具体资源,查看响应头中的 Content-Encoding(Gzip 是否启用)和 Cache-Control(缓存策略)。重复刷新后状态栏显示「from disk cache」说明浏览器缓存已命中。

小结

  • Gzip 只压缩文本类型,级别 6 是速度与压缩率的平衡点
  • 静态资源按类型设置合理的 expires,HTML 不缓存或短缓存
  • CSS/JS 长缓存须配合版本化文件名
  • 用 curl --compressed 和开发者工具验证配置效果

常见问题

gzip_comp_level 设多少合适?

推荐 5-6。级别越高压缩率越好但 CPU 开销越大,级别 9 相比 6 压缩率提升有限但 CPU 消耗翻倍。对大多数 VPS 场景,6 是性价比最高的选择。

开启 Gzip 后 HTTPS 有安全风险吗?

早期 BREACH 攻击针对特定场景(页面包含 CSRF token 等秘密且可被攻击者注入内容时)。对一般内容网站影响极小,开启 Gzip + HTTPS 的收益远大于理论风险。

expires -1 和 no-cache 有什么区别?

expires -1 生成 Expires 为过去时间(立即过期),no-cache 表示每次使用缓存前需向服务器验证是否过期(可用304复用缓存)。对于需要频繁更新的内容,no-cache 是更标准的写法。