合者离之始
Record:005

给个人博客定一份性能预算

没有预算的性能优化是玄学。把「别太慢」变成可检查的数字,才知道哪次改版是退步。

Posted2026-06-12Words1196Reading3 min

「这个站挺快的」不是一个可以复现的判断。要让它可复现,得先有预算。

预算从哪来

三个来源,按可靠性排序:

  1. 实测的 Core Web Vitals(p75,移动端)
  2. 竞品/同类站点的体积(不是拍脑袋,是量出来的)
  3. 你自己上一版的数据(这是最有用的对照)

我的博客是纯静态、内容型,所以预算按「文字优先」定:

资源目标上限
HTML≤ 20KB40KB
CSS≤ 25KB40KB
JS(文章页)≤ 20KB40KB
字体≤ 100KB150KB
首屏总传输≤ 250KB400KB
LCP≤ 2.0s2.5s
CLS≤ 0.050.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。

一个反直觉的观察

我做过的所有性能优化里,收益最大的三个都不涉及代码:

  1. 去掉 Google Fonts 外链(省了一次跨域往返 + 200KB)
  2. 把首屏的图片改成 CSS 渐变(省了一个请求)
  3. 删掉一个统计脚本(省了 40KB 和一个长任务)

性能优化的第一原则不是「写得更快」,而是「少加载点东西」。

至于预算本身,它的价值不在数字,而在于让「这次改版变慢了」变成一个能在 CI 里自动发现的事实,而不是三个月后有人抱怨「网站怎么这么卡」。