Web 开发

把首屏从 3 秒压到 1 秒以内,绝大多数收益来自三件事:缓存、压缩、少发请求。这篇按收益从高到低排列。

第一优先:让静态资源带上长缓存

浏览器每次访问都要判断资源是否过期,这个往返本身就是成本。给静态资源加一年缓存,并用文件名指纹来失效:

location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
    access_log off;
}

immutable 告诉浏览器「这个文件在有效期内绝对不会变」,连条件请求都省了。

配套要求:文件内容变了,文件名必须变。常见做法是加 hash,例如 style.a1b2c3.css

第二:开启压缩

gzip on;
gzip_comp_level 5;          # 6 以上收益很小但 CPU 明显上升
gzip_min_length 1024;       # 太小的文件压缩不划算
gzip_types text/plain text/css application/javascript application/json
           image/svg+xml application/xml;

# 预压缩的文件优先直接发送
gzip_static on;

# 新版本浏览器优先用 brotli(需编译模块)
# brotli on;
# brotli_comp_level 5;
# brotli_types text/css application/javascript application/json image/svg+xml;

HTML 一般能压到 20% 左右,CSS/JS 能到 25%。这是纯收益,只要注意别把 gzip_comp_level 调太高。

第三:减少请求数与体积

  • 图片:统一转 WebP,通常比 JPEG 小 25%–35%。<img> 上加 loading="lazy"(首屏图片除外)和 width/height 避免布局抖动。
  • 字体:优先用系统字体,或只加载用到的字重。中文字体整包动辄几 MB,务必做子集化。
  • 关键 CSS:把首屏样式内联进 <head>,其余异步加载,可显著改善首次渲染时间。
<link rel="preload" href="/style.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>

验证方法

不要凭感觉。用命令行确认压缩与缓存是否真的生效:

curl -sI -H 'Accept-Encoding: gzip' https://it365.wang/ | grep -Ei 'content-encoding|cache-control'

期望输出里同时出现 content-encoding: gzipcache-control: public, ...。如果没有,说明配置没匹配上——优先检查 gzip_types 是否漏了你实际用的 MIME 类型。

小结

顺序:长缓存 → 压缩 → 减少请求。前两步是配置改动,收益最大;第三步涉及前端资源组织,收益次之但更持久。做完用 curl -sI 逐项验证,别停在「应该生效了」。

参与讨论