给个人网站设一份性能预算
不追求抽象的满分,而是用字体、脚本、图片和交互指标约束每一次功能增长。
个人网站最容易在“只加一点”的过程中变慢:一套字体、一个统计脚本、两张未经处理的封面,再加上广告和评论。每项单独看都不夸张,组合起来却足以让移动网络上的首屏等待数秒。
性能预算的作用,是在功能进入页面之前给出边界。它不是追求某个工具里的 100 分,而是把用户能感知的速度转成团队——哪怕团队只有一个人——可以执行的约束。
先定义体验目标
Core Web Vitals 提供了三个有用视角:LCP 观察主要内容何时出现,INP 关注交互响应,CLS 衡量布局是否突然跳动。它们不能覆盖全部体验,但能避免只盯着服务器响应时间。
可以从一份朴素预算开始:
| 指标 | 移动端目标 |
|---|---|
| 首次加载传输量 | 小于 500 KB |
| 首屏关键 CSS | 小于 30 KB |
| 初始 JavaScript | 小于 100 KB |
| LCP | 75% 访问低于 2.5 秒 |
| CLS | 低于 0.1 |
这些数字不是法律。图像作品集与文字博客的合理预算不同。重点是有一条需要主动讨论才能越过的线。
字体:最容易忽略的资产
中文字体包含大量字形,完整文件可能达到数 MB。为了视觉一致而让每位访客下载整套字体,通常得不偿失。
正文优先使用系统字体是可靠选择。如果品牌确实需要 Web Font,可以只在拉丁字符或标题中使用,并设置 font-display: swap。字体预加载要克制:预加载了却没有立即使用的资源,会与真正关键的 CSS 和图片竞争带宽。
JavaScript:按交互需要支付
静态文章不应该为了显示导航栏而下载一整个前端框架。页面能够由 HTML 和 CSS 完成的部分,在构建时输出即可。真正需要状态的工具,再把脚本限制在对应组件。
评估一个依赖时,不只看 npm 页面上的压缩体积,还要问:
- 它是否进入每个页面的初始包?
- 是否能按路由或交互时机延迟加载?
- 原生 Web API 是否已经覆盖需求?
- 更新频率与安全维护是否匹配项目寿命?
删除 30 KB 脚本往往比把它压缩得更精巧有效。
为媒体保留空间
图片应提供明确的 width 和 height,让浏览器在文件下载前就能计算比例。这一项简单设置可以消除大量 CLS。首屏主图不要懒加载;屏幕以下的图片则应使用原生 loading="lazy"。
响应式图片需要按实际展示尺寸生成多个版本。给 360 像素宽的手机发送 2400 像素图片,即使格式是 WebP,也仍在浪费流量。
广告同样需要空间预算。如果广告容器加载前高度为零,加载后突然撑开正文,页面就会明显跳动。为常见版位设置最小高度,并避免把广告紧贴下载或操作按钮。
在发布流程里执行预算
写在文档里的预算很容易被忘记。更好的做法是让构建过程报告产物大小,并在持续集成中运行 Lighthouse 或同类检查。真实用户数据则告诉你实验室环境没有覆盖的设备与网络。
不必为每一次轻微波动阻断发布,但显著退化必须能被看到。每月保留一份趋势,比偶尔手工跑一次满分截图更有价值。
性能是一种持续的产品选择。设定预算之后,“加入这个功能吗”会自然变成更具体的问题:它为用户创造的价值,是否值得它占用的加载与交互成本?