用途
该技能用于处理性能优化任务。适用入口包括:性能不达标(例如 LCP > 2.5s、页面响应慢)、慢页面调查、上线前的性能审查,或用户提到"性能""慢""latency""优化"等关键词。其出口是获得可量化的性能改善并加上回归测试,之后可回到 verify-workflow-review 或 ship-workflow-ship。前置加载为 CANON.md,输出路径为性能改善报告,交由 verify-workflow-review 审查。
不适用的情况:没有可量化的性能目标、基线或用户可感知慢点;只是常规代码清理或可读性优化;问题首先是功能错误、安全风险或架构边界不清。
核心流程
铁律流程为 MEASURE → IDENTIFY → FIX → VERIFY → GUARD:
- MEASURE:收集指标(Lighthouse、RUM、profiler)。
- IDENTIFY:定位瓶颈,找出最大的一个瓶颈。
- FIX:一次改一个,只修测量证明有问题的部分。
- VERIFY:重新测量,对比 before/after。
- GUARD:加入回归测试或性能预算。
Core Web Vitals 目标
指标 | Good | Needs Work | Poor LCP(最大内容绘制) | ≤ 2.5s | 2.5-4.0s | > 4.0s INP(交互到下一次绘制) | ≤ 200ms | 200-500ms | > 500ms CLS(累积布局偏移) | ≤ 0.1 | 0.1-0.25 | > 0.25
TTFB(首字节时间):≤ 800ms 为良好。
瓶颈定位
前端瓶颈:大 JS Bundle(> 200KB gzipped)对应代码拆分/lazy loading;大图片(> 500KB)对应压缩/WebP/响应式尺寸;布局偏移对应显式 width/height;长任务(> 50ms)对应拆分或 Web Worker;未缓存对应设置 Cache-Control header。
后端瓶颈:慢查询对应 EXPLAIN ANALYZE 加索引;N+1 Queries 对应 JOIN/batch 加载;无分页对应游标或偏移分页;缺失缓存对应 Redis/内存缓存热点数据;同步阻塞对应异步/队列。
常见修复示例
N+1 查询——Bad:在循环中为每个 task 额外查询一次 assignee(每个 task 增加一次查询);Good:使用一次 JOIN 加载(db.tasks.findMany({ include: { assignee: true } }))。
无界查询——Bad:直接返回全部数据;Good:加入分页与限制,使用 page、pageSize,take: Math.min(pageSize, 100) 作为硬上限,并在响应中返回分页信息。
图片优化——使用 srcset 提供响应式尺寸、WebP 等现代格式、显式 width/height、loading="lazy"。
缺失缓存——Cache-Control 策略:静态资源(JS/CSS/Fonts)用 max-age=31536000, immutable;图片用 max-age=86400;变化慢的 API 响应用 max-age=60, stale-while-revalidate=300;实时 API 响应用 no-store。
性能预算——以 JSON 配置形式设定:script 200KB gzipped、style 50KB、LCP 2500ms、CLS 0.1。
验证证据
输出或记录必须包含:输入/来源(读取的 spec、plan、代码、反馈或发布上下文);执行动作(实际完成的检查、生成、修复、导出或发布步骤);验证结果(命令、审查结论、产物路径、截图或人工确认);阻塞/回退(未通过项、回退路径或需要 human partner 决策的问题)。
常见说辞与现实
- "我本地很快":本机不等于用户的 4G Android,应用 Lighthouse(模拟 4G + mid-tier CPU)测量。
- "多加点缓存就行":缓存会掩盖问题,应先修查询/加载再缓存。
- "React.memo + useMemo 全加了":过度 memo 与不够 memo 一样有害,每个 memo 都有比对成本,需测量清楚哪里需要。
- "先上线,性能以后优化":上线后性能问题已影响用户,应从第一天起设置预算。
- "优化所有瓶颈":只优化最大的那个,其余除非测量证明值得否则不修。
红旗 — STOP
没有测量就开始"优化";将多个性能修复打包在一起;优化后不重新测量;过早优化;N+1 查询在循环中出现;列表端点没有分页。
验证清单
Before 和 After 测量数据存在;性能改善量化(例如 LCP 从 Xms → Yms);没有引入新的性能回归;添加性能回归测试或 CI 预算检查;只修改了测量证明有问题的部分;N+1 查询检测通过;列表端点有分页限制。
验证失败处理
- 没有测量数据就开始优化:STOP,回到 MEASURE 收集数据,没有基线等于猜谜。
- 优化后性能无改善:回退修复,重新定位瓶颈,回到 IDENTIFY。
- 优化引入功能回归:回退优化,先修复回归再重新测量。
- 无法复现性能问题:模拟生产条件(4G 网络 + mid-tier CPU + 真实数据量)。
- 多个瓶颈同时存在:只修最大的那个,修完重新测量后再看下一个。
好坏示例
Good:Lighthouse 测得 LCP 4.2s → 定位 N+1 查询为瓶颈 → 一次改一个 → 重测 LCP 1.8s(改善 57%)→ 加性能预算,每步有测量数据。
Bad:"我加了缓存,页面应该快了"——没有 before/after 数据、没有瓶颈定位、没有重新测量。
输出模板
完成后产出必须包含:Baseline(LCP、INP、CLS 的 before/after 及改善百分比);Bottleneck Identified(位置、类型、测量证据);Fix Applied(改动、文件、变更行数);Verification(before/after 对比、无功能回归、性能预算检查)。