「这个站挺快的」不是一个可以复现的判断。要让它可复现,得先有预算。
预算从哪来
三个来源,按可靠性排序:
- 实测的 Core Web Vitals(p75,移动端)
- 竞品/同类站点的体积(不是拍脑袋,是量出来的)
- 你自己上一版的数据(这是最有用的对照)
我的博客是纯静态、内容型,所以预算按「文字优先」定:
| 资源 | 目标 | 上限 |
|---|---|---|
| HTML | ≤ 20KB | 40KB |
| CSS | ≤ 25KB | 40KB |
| JS(文章页) | ≤ 20KB | 40KB |
| 字体 | ≤ 100KB | 150KB |
| 首屏总传输 | ≤ 250KB | 400KB |
| LCP | ≤ 2.0s | 2.5s |
| CLS | ≤ 0.05 | 0.1 |
超过上限的提交,要么改,要么在 PR 里写清楚为什么值得。
最容易超支的三处
1. 字体
一个中文字体动辄 5-20MB。我现在的做法是:中文零 webfont,只用系统字体栈;拉丁文用两个子集。
--font-ui: "Manrope", -apple-system, "Segoe UI", "PingFang SC",
"Microsoft YaHei", sans-serif;只 preload 首屏真正用到的字重,其余交给 unicode-range 按需加载。
2. 组件库的「顺手引入」
哪怕只用一个按钮,打包器也可能把整套样式带进来。构建完扫一遍产物:
# 找出最大的几个产物
du -h dist/_astro/* | sort -rh | head我遇到过评论组件把 24KB 的 CSS 提升成全局阻塞样式表——因为 import '@waline/client/style' 被 Vite 提取到了主样式。改成运行时插入 <link> 才解决。
3. 客户端路由与第三方脚本
评论、统计、嵌入视频,全都应该在「需要时」才加载。判断标准很简单:它是不是首屏阅读的一部分。
不是 → 懒加载。
怎么守住
三个层次,从软到硬:
第一层:构建时看体积
npm run build && du -sh dist第二层:CI 里设阈值
在 GitHub Actions 里比较这次和上次的产物大小,超过就失败。
第三层:真实用户数据
本地 Lighthouse 是实验室数据,室内温度永远比室外好看。上线后看 CrUX 或自建 RUM 的 p75。
一个反直觉的观察
我做过的所有性能优化里,收益最大的三个都不涉及代码:
- 去掉 Google Fonts 外链(省了一次跨域往返 + 200KB)
- 把首屏的图片改成 CSS 渐变(省了一个请求)
- 删掉一个统计脚本(省了 40KB 和一个长任务)
性能优化的第一原则不是「写得更快」,而是「少加载点东西」。
至于预算本身,它的价值不在数字,而在于让「这次改版变慢了」变成一个能在 CI 里自动发现的事实,而不是三个月后有人抱怨「网站怎么这么卡」。