
背景
网站图片多、首次打开慢,除了带宽限制外,网站本身能做的优化其实还有不少。这次实测做了两件性价比很高的事:给静态资源加浏览器缓存头、批量压缩图片。效果显著:首页图片体积从 6MB 压到 1MB 以内,复访基本秒开。这篇记录具体做法和踩坑。
过程
优化一:给静态资源加浏览器强缓存头
很多人以为「缓存」是 CDN 才有的,其实最基础、最有效的一步是让浏览器本地缓存静态资源。
症状
所有图片、CSS、JS 的响应头只有一个 ETag,没有 Cache-Control 和 Expires。意味着浏览器每次打开页面,即使图片没变,也要重新向服务器发请求(协商或重新下载)。复访也慢,白白浪费带宽。
解法:nginx 反代层加缓存头
对图床这种上传后不变的图片,设长缓存很安全:
location / {
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable" always;
proxy_pass http://127.0.0.1:9000;
}对主站里可能更新的附件/CSS/JS,取 7 天比较稳妥。关键是区分:不可变的图床图用 immutable 长缓存,可能改的动态资源用短缓存。
一个坑:正则 location 的优先级
主站反代是一个 location ~ / 吞掉所有请求。如果想把缓存规则单独写在 server 层的新 location,会因为正则优先级永远匹配不到(nginx 正则是按出现的先后,第一个命中的生效)。必须写在 location ~ / 里面用 if 判断:
location ~ / {
if ($request_uri ~* "\.(jpg|jpeg|png|gif|webp|css|js)(\?.*)?$") {
expires 7d;
add_header Cache-Control "public, max-age=604800";
}
proxy_pass http://127.0.0.1:915;
}注意正则要带 (\?.*)?$——因为 CSS 常带版本号参数(如 style.css?k05),不然匹配不到。
效果
加缓存头后,复访时静态资源直接从浏览器本地缓存取,零网络请求,页面秒开。
优化二:批量压缩图片
症状
首页 block 缩略图表面是 350×250 的小图,体积却有 135~160KB——明显是 JPEG 编码质量设得过高。350×250 的图正常只要 15~30KB。
排查确认
用 ImageMagick 查看真实尺寸与体积:
convert 图片.jpg -format '%wx%h %b' info: # 输出: 350x250 135.63KB确认是「图已经小,但质量参数虚高」。
解法:批量重压
备份后批量压到 quality 70(对缩略图视觉无损):
for f in /www/data/attachment/block/*/*.jpg; do
convert "$f" -strip -quality 70 "$f"
done效果
| 指标 | 压缩前 | 压缩后 |
|---|---|---|
| 首页 block 缩略图总量 | 11.5 MB | 1.0 MB(-91%) |
| 首页全部唯一图片 | 6143 KB | 705 KB |
首页首次打开从 53 秒降到 14 秒(在带宽允许的理想情况下)。
补充:别忽略 Gzip
CSS/JS 这种文本资源,Gzip 压缩率极高。实测一个 405KB 的 CSS,gzip 后传输只有 71KB(-82%)。nginx 通常默认开了 gzip on(gzip_types 含 css/js/text),改配置前先 curl -I -H 'Accept-Encoding: gzip' 看有没有 content-encoding: gzip,别重复配置。
测速小贴士:curl 默认不带Accept-Encoding,会拿到未压缩体积,导致误以为资源很大很慢。加--compressed才模拟浏览器真实行为。
总结
正确做法
- 先查响应头:
Cache-Control、Content-Encoding——看清缓存和压缩到底开没开,别凭感觉重复配置 - 区分资源性质设置缓存:图床不可变图用长缓存 +
immutable;可能更新的附件/CSS/JS 用短缓存 - 图片压缩优先看「质量参数是否虚高」——小图体积巨大通常是 quality 太高,压到 70~75 缩略图视觉无损
- 能压的都压:gzip(文本)+ 图片压缩(-90%)+ 缓存头(复访秒开),这仨是网站层性价比最高的免费优化
注意
- 图片压缩先备份再批量操作,防止质量不可逆损坏
- 正则 location 有优先级坑,缓存规则要写对位置才生效
- 网站优化做到底之后,如果还慢,就要回到「带宽/入口」这个物理层去看了(见另一篇《网站访问慢?先分清是网站问题还是带宽问题》)
参考:Nginx ngx_http_headers_module(expires/add_header),ImageMagick convert
觉得内容不错?我要