前端性能优化清单:从加载到交互的 20 个检查项
约 1 分钟· 687 字 122 次阅读
性能优化最容易踩的坑是"凭感觉优化"。正确的姿势是用数据定位,按清单排查。这份清单按三个阶段组织,每个检查项都给了判断标准。
第一阶段:加载(Load)
1. 资源体积是否超标
# 看打包产物
npx next build | grep -E "First Load|Route"
# 大包警告:> 200KB 要警惕
标准:首屏 JS < 150KB(gzip),超了就拆包。
2. 图片是否优化
- 格式:用 WebP/AVIF 代替 PNG/JPG;
- 尺寸:不要加载 2000px 的图显示在 300px 的位置;
- 懒加载:
loading="lazy"给非首屏图。
3. 字体是否阻塞
font-display: swap 防止 FOIT(字体导致首屏不可见)。大字体文件用 subset 只加载用到的字符:
@font-face {
font-family: "Zpix";
src: url("/fonts/zpix-subset.woff2");
font-display: swap;
}
第二阶段:渲染(Render)
4. 有没有大图/渐变阻塞
CSS 渐变和 box-shadow 大面积使用会拖慢合成。用性能面板看 Long Task:
// Performance 面板 → 录制 → 看长任务
// > 50ms 的任务就是卡顿来源
5. 关键 CSS 是否内联
首屏要用的样式内联在 <head>,避免 CSS 文件回来前无样式。
6. 是否做了代码分割
// 只在用到时才加载
const Mermaid = dynamic(() => import("./Mermaid"), { ssr: false });
第三阶段:交互(Interaction)
7. 事件是否高频触发
滚动、resize、输入事件要防抖/节流:
// 防抖:停止操作 300ms 后才执行
const debounced = useMemo(() => debounce(save, 300), []);
8. 是否有不必要的重渲染
React 里检查:
useMemo/useCallback是否滥用(用错反而更慢);- 大列表有没有
key且稳定; - 状态是否过度提升(一个输入框的 state 拖着整个页面重渲染)。
9. 动画是否用了 transform/opacity
只改 transform/opacity 才能走合成线程,top/left/width 会触发重排:
/* ❌ 触发 layout */
element.style.left = x + "px";
/* ✅ 只走合成 */
element.style.transform = `translateX(${x}px)`;
10. 是否缺少骨架屏/加载态
即时反馈比"转圈等数据"体验好得多——首屏先出骨架,数据回来再替换。
用工具确认,不要猜
| 指标 | 工具 |
|---|---|
| LCP / FCP / CLS | Lighthouse、PageSpeed |
| 长任务 | Performance 面板 |
| 包体积 | bundle-analyzer |
| 实际用户 | Web Vitals(真实环境数据) |
一个实用流程:
- Lighthouse 跑一遍拿基线;
- 按分数低的项逐条对照本清单;
- 优化完再跑,对比分数。
性能预算
给项目设个"预算"防止退化:
| 预算 | 值 |
|---|---|
| 首屏 JS | < 150KB gzip |
| LCP | < 2.5s |
| CLS | < 0.1 |
| 单次长任务 | < 50ms |
小结
性能优化没有银弹,但有纪律:
- 先测量再动手,别凭感觉;
- 按清单逐项排查,不遗漏;
- 设预算防退化,持续监控。
优化不是一次性活动,是贯穿开发过程的习惯。