---
title: 给页面定性能预算：把'快'变成可验收的数字
url: https://vabora.dev/posts/performance-budget-web
author: Vabora
published: 2026-07-20 10:00:00
updated: 2026-09-27 10:33:42
category: 最佳实践
tags: 最佳实践, 前端, 性能
canonical: https://vabora.dev/posts/performance-budget-web
license: 转载与引用请注明出处并保留原文链接
---

# 给页面定性能预算：把"快"变成可验收的数字

> "页面要快"没法验收，"首页 gzip 后不超过 10KB、请求数不超过 6 个"可以。这篇讲怎么定性能预算、怎么自动化守住，以及超预算时该砍什么。
## 背景

"页面要快"是句正确但无法验收的话。落到日常开发里，它通常表现为：上线前大家觉得还行，三个月后没人记得当初是多少，于是每次加功能都"就多一点点"，一年后首页变成 800KB。

解法是**定数字**：把预算写下来，并让它能被自动检查。

## 定预算

先看现状，再留余量。以本站首页为例（实测值）：

| 指标 | 预算 | 当前实测 |
|---|---|---|
| HTML（gzip 后） | ≤ 12 KB | 9.8 KB |
| CSS 请求数 | ≤ 2 | 2 |
| JS 请求数 | ≤ 4 | 4 |
| CSS + JS（gzip 后） | ≤ 35 KB | 28 KB |
| 首屏图片 | ≤ 1 张且 < 100 KB | 0（纯排版） |
| 第三方脚本 | 0 | 0 |

定这两个门槛的判断依据：

- **请求数比体积更影响体感**：在移动网络下，多一个请求就是多一次往返（数百毫秒起）；
- **HTML 的 gzip 后体积最能反映"服务端渲染是否干净"**：9.8KB 说明没有把数据全塞进页面再让前端重排。

## 自动守住

### 1. 用命令随时复核

```bash
# 首页 HTML 的 gzip 体积
curl -s -H 'Accept-Encoding: gzip' https://vabora.dev/ | wc -c

# 请求数
curl -s https://vabora.dev/ | grep -c '<script'
curl -s https://vabora.dev/ | grep -c '<link rel="stylesheet"'
```

写进项目就以测试的形式固定下来（断言阈值，超了就红）：

```php
$html = MarkdownService::render('...'); // 或抓取真实页面
$t->true(strlen(gzencode($html, 6)) < 12 * 1024, '首页 gzip 后 < 12KB');
```

### 2. 视觉回归之外的"体积回归"

改样式时最容易悄悄变胖（多引入一个字体、多一张图、多一段动画）。所以体积断言要跟代码一起跑，而不是季度末人工体检。

## 超预算时砍什么

按这个顺序做取舍，几乎总是对的：

1. **先砍第三方脚本**：一个统计 + 一个客服 + 一个 A/B 工具，很容易超过你整站 CSS 的体积，而收益最不明确；
2. **再砍首屏图片**：改成 CSS 渐变/图案，或用 `<img loading="lazy">` 推后；
3. **再压字体**：中文字体是重灾区，能只用系统字体就别自托管（本站的做法）；必须自托管时用 `font-display: swap` + 子集化；
4. **最后才讨论压缩与拆分**：它们省的是百分比，而前三条省的是倍数。

## 结果

- 首页 gzip 后 9.8KB、全站 CSS+JS gzip 后 28KB，移动网络下首屏基本瞬时；
- 加新功能时有明确的天花板：想加一个 20KB 的库，就得先说清砍掉什么；
- "性能"从主观感受变成数字，讨论成本大幅下降。

## 取舍

- **不为一个指标牺牲可用性**：比如为了少一个请求把 3 个页面的 JS 全合并，会让"改 A 影响 B"的风险上升。预算约束的是总量，不是逼你违背模块化。
- **不追 Lighthouse 满分**：分数受环境影响大且波动明显，容易变成数字游戏。用固定命令量的体积与请求数更稳定可靠。
- **不做早期过度优化**：预算的作用是"防退化"，不是"逼你现在就优化"。当前值离预算还远时，先把功能做对。
