Claude Code 性能优化:从测量到 Core Web Vitals 改善
用 Claude Code 量化并优化 LCP、INP、API 延迟、包体积与缓存,附可运行示例。
Web 应用的性能优化,不是笼统地“让它快一点”。它要把用户等待首屏的时间、点击后没有反应的时间、图片或广告导致的布局跳动、服务器多花掉的 CPU 和数据库查询,都变成可以比较的数字,再用小而明确的改动去降低这些数字。
Claude Code 很适合这类工作,因为它可以阅读代码、追踪可能的瓶颈、提出补丁,并补上验证步骤。但顺序很重要:先测量,再提出假设,只改一处,再用同样的方法复测。如果只输入“帮我优化性能”,很容易得到看起来合理但无法证明有效的修改。
建议同时参考官方资料:web.dev Core Web Vitals、Lighthouse docs 和 MDN Performance API。
先定义什么叫快
性能不是一个分数。LCP(Largest Contentful Paint)表示主要内容出现的时间;INP(Interaction to Next Paint)表示点击、输入等交互后的响应重量;CLS(Cumulative Layout Shift)表示加载过程中页面是否发生意外移动。
应用层还要看 API p75 延迟、数据库查询次数、JavaScript 包体积、图片传输量,以及浏览器主线程上是否有耗时计算。p75 是 75 分位值,比平均值更能反映大多数用户会遇到的慢体验。
flowchart LR
Measure["测量"] --> Hypothesis["提出假设"]
Hypothesis --> Patch["小步修改"]
Patch --> Verify["再次测量"]
Verify --> Keep["只保留有效改动"]
| 指标 | 含义 | 初始目标 |
|---|---|---|
| LCP | 主要内容出现时间 | 尽量不超过 2.5 秒 |
| INP | 交互响应速度 | 尽量不超过 200ms |
| CLS | 意外布局移动 | 尽量低于 0.1 |
| API p75 | 多数用户感受到的接口延迟 | 按页面定义目标 |
| JS 传输量 | 首屏加载的 JavaScript | 按路由比较差异 |
给 Claude Code 更好的输入
高质量请求应该包含症状、复现方式、当前数字和限制条件。
仓库里的 /products 页面很慢。
目标是降低移动端 LCP 和 /api/products 的 p75 延迟。
当前测量:
- Lighthouse mobile Performance: 58
- LCP: 4.2s
- INP: 180ms
- CLS: 0.04
- /api/products p75: 920ms
请:
1. 按图片、包体积、API、数据库访问的顺序调查。
2. 不要只凭猜测改代码,请写出文件名和依据。
3. 优先选择影响范围小、可测量的改动。
4. 给出修改后我需要运行的验证命令。
相关内部文章可以继续看:Claude Code 调试技巧完整指南、用 Claude Code 加速 React 开发 和 Claude Code 图片优化指南。
可运行的测量脚本
Node.js 18 以上可以直接运行下面的脚本,用来测页面或 API 的平均延迟和 p75。
// measure-url.mjs
import { performance } from "node:perf_hooks";
const url = process.argv[2] ?? "https://example.com/";
const runs = Number(process.argv[3] ?? 5);
async function measureOnce() {
const start = performance.now();
const res = await fetch(url, { cache: "no-store" });
await res.arrayBuffer();
return {
status: res.status,
ms: performance.now() - start,
};
}
const samples = [];
for (let i = 0; i < runs; i += 1) {
samples.push(await measureOnce());
}
samples.sort((a, b) => a.ms - b.ms);
const avg = samples.reduce((sum, s) => sum + s.ms, 0) / samples.length;
const p75Index = Math.floor((samples.length - 1) * 0.75);
const p75 = samples[p75Index].ms;
console.table(
samples.map((sample, index) => ({
run: index + 1,
status: sample.status,
ms: sample.ms.toFixed(1),
}))
);
console.log(`avg=${avg.toFixed(1)}ms p75=${p75.toFixed(1)}ms`);
node measure-url.mjs http://localhost:3000/api/products 7
把这个输出交给 Claude Code,就能比较修改前后的真实差异,而不是只讨论“感觉快了”。
真实用例
| 场景 | 常见原因 | 可以让 Claude Code 做什么 |
|---|---|---|
| SaaS 仪表盘首屏慢 | 所有组件首屏同时请求,图表库很大 | 延迟非关键组件,拆分图表代码 |
| 电商商品列表慢 | 图片过大,库存和评论出现 N+1 查询 | 调整图片尺寸,检查 include/select |
| 内容文章 LCP 差 | 头图加载晚,广告脚本抢资源 | 优先主图,延迟第三方脚本 |
| 管理后台搜索卡顿 | 大数组在主线程同步过滤 | 降低复杂度、分页或移到后台处理 |
N+1 指先查一次列表,再对每一行追加一次查询。少量数据时看不出来,数据一多就会突然变慢。缓存是短时间复用结果的机制,但权限、个人信息、价格和库存不能随便放进共享缓存。
可运行的缓存示例
下面的 Express 示例包含一个故意延迟的接口和一个带缓存的接口。生产环境常用 Redis 或 CDN,但内存缓存更适合理解机制。
npm init -y
npm install express
node cached-api.mjs
// cached-api.mjs
import express from "express";
import { performance } from "node:perf_hooks";
const app = express();
const cache = new Map();
const ttlMs = 30_000;
async function loadProducts() {
await new Promise((resolve) => setTimeout(resolve, 800));
return [
{ id: 1, name: "Starter Plan", price: 1200 },
{ id: 2, name: "Pro Plan", price: 4800 },
];
}
async function cached(key, loader) {
const now = Date.now();
const hit = cache.get(key);
if (hit && hit.expiresAt > now) return { data: hit.data, cache: "hit" };
const data = await loader();
cache.set(key, { data, expiresAt: now + ttlMs });
return { data, cache: "miss" };
}
app.get("/api/products/raw", async (_req, res) => {
const start = performance.now();
const data = await loadProducts();
res.json({ cache: "none", ms: performance.now() - start, data });
});
app.get("/api/products/cached", async (_req, res) => {
const start = performance.now();
const result = await cached("products", loadProducts);
res.json({ ...result, ms: performance.now() - start });
});
app.listen(3000, () => {
console.log("Open http://localhost:3000/api/products/raw");
});
node measure-url.mjs http://localhost:3000/api/products/raw 3
node measure-url.mjs http://localhost:3000/api/products/cached 3
让 Claude Code 加缓存时,要明确范围:热门商品缓存 30 秒、库存不缓存、登录用户信息必须把 userId 放进 key。
可运行的算法示例
卡顿不一定来自网络。浏览器主线程上的同步计算太重,也会让 INP 变差。下面把重复 includes 扫描换成 Set。
// compare-lookup.mjs
import { performance } from "node:perf_hooks";
const a = Array.from({ length: 40_000 }, (_, i) => i);
const b = Array.from({ length: 40_000 }, (_, i) => i * 2);
function slowIntersection(left, right) {
return left.filter((item) => right.includes(item));
}
function fastIntersection(left, right) {
const rightSet = new Set(right);
return left.filter((item) => rightSet.has(item));
}
function time(label, fn) {
const start = performance.now();
const result = fn();
const ms = performance.now() - start;
console.log(`${label}: ${ms.toFixed(1)}ms (${result.length} hits)`);
}
time("slow", () => slowIntersection(a, b));
time("fast", () => fastIntersection(a, b));
node compare-lookup.mjs
常见失败
不要只追 Lighthouse 分数。Lighthouse 是实验室数据,真实用户的设备、网络、缓存和扩展都不同。要结合 Search Console、真实用户监控和服务器日志。
不要在没有正确性规则的情况下加缓存。价格、库存、权限、个人数据都需要清楚的 cache key、TTL 和失效策略。
不要到处加 useMemo。React 的 memo 化只应该保护已经测量过的热点,否则会增加依赖数组错误和维护成本。
不要把所有图片都设为优先加载。首屏图片需要稳定尺寸和必要的优先级,首屏以下图片通常应该保持懒加载。
不要盲目拆包。可以结合 Claude Code 包体积分析 和 Claude Code 代码分割 按路由比较影响。
写进 CLAUDE.md
## Performance rules
- Before optimizing, record the current metric and target metric.
- Prefer small, measurable changes over broad rewrites.
- Do not introduce shared cache for user-specific data.
- Avoid N+1 queries; use select/include or batching.
- Keep above-the-fold images sized and stable.
- After changes, report commands used for verification.
这些规则会让 Claude Code 更关注可证明的改进,而不是只改表面。
咨询 CTA
ClaudeCodeLab 可以帮助用 Claude Code 审计现有 Web 应用、改善 Core Web Vitals、定位 API/数据库延迟,并整理可执行的性能优化手册。第一次咨询时,最好准备目标 URL、关键页面、Lighthouse 结果、慢 API 日志和期望完成时间。
实测结果
本地运行示例时,故意延迟的 /api/products/raw 大约保持在 800ms,而 /api/products/cached 从第二次请求开始会降到几毫秒。compare-lookup.mjs 也能看到 Set 版本明显更快。真实项目不会总是这么整齐,但“先测 p75、只改一处、用同一工具复测”这个流程非常稳定。
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
Claude Code Permission Receipt Pattern:记录权限、证据和回滚方式
Claude Code 权限 receipt:记录允许动作、需要批准的边界、验证命令、回滚说明,以及 Gumroad 和咨询 CTA 检查。
Claude Code/Codex 安全 Agent Harness 实战:权限、验证与回滚
用权限策略、执行计划、验证脚本和回滚日志,为 Claude Code 与 Codex 搭建更安全的 AI Agent 工作流。
Claude Code 子代理实战指南:安全委派并行文章与代码工作
用 Claude Code 子代理安全拆分文章和代码工作:委派规则、提示词模板、失败模式与检查清单。