Tips & Tricks (更新: 2026/7/23)

Claude Code 处理慢 Node.js:先测瓶颈再修改

用 Claude Code、计时器、用例、陷阱和验证步骤,按测量结果优化 Node.js 后端处理。

Claude Code 处理慢 Node.js:先测瓶颈再修改

你的 Node.js 报表接口很慢,发布窗口快到了,同事第一句话是“加索引”。这也许正确,但在计时结果出来之前,它仍然只是猜测。慢接口最怕的不是代码复杂,而是团队把时间花在根本不慢的地方。

本文把 Claude Code 当作编程助手,而不是性能问题的占卜工具。瓶颈指限制整个请求速度的最慢部分。性能分析指用时间数据看清瓶颈在哪里。安全的顺序是:加小范围计时,使用合成数据运行一个可复现命令,只修最慢的一段,再用同一个命令复查。

这里讨论的是服务端 Node.js:API 处理器、批处理脚本、CSV 导出和数据加工。浏览器首屏、图片、布局抖动属于另一类问题,请看 Core Web Vitals 性能指南。如果计时结果落在 SQL 查询里,再进入 SQL 优化指南

先做什么

先找最小的工作对象:一个路由、一个脚本、一个 fixture,或一个 CSV 导出命令。在还没有复现命令之前,不要让 Claude Code “把整个项目变快”。范围越小,读取文件越少,最后交给人审查的证据也越清楚。

先定义术语。N+1 问题指先取一次列表,再对列表里的每一项各查一次关联数据。串行 await 指互不依赖的异步工作被迫按顺序等待。记忆化指同一个输入复用同一个结果,而不是在循环里反复计算。

实际排查时,还要把“慢”的边界写清楚。是单个 API 在本地慢,还是批处理在 CI 里慢?是读取 100 行慢,还是写出 10 万行 CSV 慢?这些边界会改变计时点。如果边界不清,Claude Code 可能会同时检查路由、中间件、数据库模型、日志配置和前端调用,最后得到一堆无法比较的建议。

我建议把第一轮问题写成一句可执行的验收条件:运行某个命令后,输出必须包含四个区间的耗时,并按从慢到快排序。这样即使没有真实生产数据,团队也能先判断该看数据库、网络、转换,还是文件写入。

初始提示词要同时限制范围和权限:

claude -p "src/api/report.ts is slow. Do not rewrite it yet.
Add timing around database fetch, API fetch, transform, and response formatting.
Use synthetic fixture data only. Return the changed files, command to run, and the slowest measured section.
Do not change production settings, billing limits, credentials, or customer-data handling without human approval."

可复制的计时代码

第一版修改应该很朴素:只打印时间,不重写服务。Node.js 官方 node:perf_hooks 文档 提供 performance.now(),所以不需要安装新包。

在测试分支或临时目录里创建 measured-report.mjs,然后用 Node 运行。示例数据是合成数据:没有密钥、令牌、生产 URL,也没有客户记录。

import { performance } from "node:perf_hooks";

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

function createTimer() {
  const records = [];
  return {
    async measure(label, fn) {
      const start = performance.now();
      const value = await fn();
      records.push({ label, ms: Number((performance.now() - start).toFixed(1)) });
      return value;
    },
    report() {
      return records.sort((a, b) => b.ms - a.ms);
    },
  };
}

async function fetchUsers() {
  await wait(60);
  return Array.from({ length: 6 }, (_, index) => ({ id: index + 1 }));
}

async function fetchOrdersOneByOne(users) {
  const orders = [];
  for (const user of users) {
    await wait(45);
    orders.push({ userId: user.id, total: user.id * 10 });
  }
  return orders;
}

async function fetchOrdersInBatch(users) {
  await wait(55);
  return users.map((user) => ({ userId: user.id, total: user.id * 10 }));
}

function buildReport(users, orders) {
  const ordersByUser = new Map(orders.map((order) => [order.userId, order]));
  return users.map((user) => ({ ...user, orderTotal: ordersByUser.get(user.id)?.total ?? 0 }));
}

async function run(fetchOrders) {
  const timer = createTimer();
  const users = await timer.measure("users", fetchUsers);
  const orders = await timer.measure("orders", () => fetchOrders(users));
  await timer.measure("report", () => buildReport(users, orders));
  console.table(timer.report());
}

console.log("slow version");
await run(fetchOrdersOneByOne);

console.log("batch version");
await run(fetchOrdersInBatch);

运行命令如下:

node measured-report.mjs
node --prof measured-report.mjs
node --prof-process isolate-*.log > profile.txt

node --prof 是内置分析器,官方 Node.js CLI 参考 有说明。简单计时看不清 CPU 消耗时再用它;很多 API 和批处理问题,用小表格已经能找到第一个修复目标。

三个使用场景

场景一:API 响应慢

输入:API 处理器、路由测试和一份合成请求。Claude Code 可以在数据库读取、外部读取、转换和序列化周围加计时。人必须批准涉及凭证、认证、流量限制或客户数据保留的改动。

输出:一张计时表和一个只针对最慢部分的小补丁。如果最慢的是查询,先看 SQL 清单,不要随手加索引。如果最慢的是 JSON 格式化,修复范围就留在应用代码里。

场景二:批量 CSV 导出

输入:本地假数据 fixture 和生成 CSV 的命令。Claude Code 可以测量行读取、关联、格式化和写文件。人必须批准从 fixture 切换到生产导出,因为那里可能包含客户数据和计算成本。

输出:说明问题来自 N+1 读取、串行调用,还是重复格式化。常见修复是批量读取、限制并发或缓存格式化器,而不是重写整个任务。

场景三:发布前审查拉取请求

输入:拉取请求差异、已有性能测试和预期响应预算。Claude Code 可以检查差异并建议补充计时。发布决定、回滚方案和对客户承诺的 SLA 必须由人批准。

输出:审查记录写清测到的风险、运行的命令和仍未测量的部分。这比“看起来更快”更能指导发布判断。

测完之后怎么改

计时症状可能原因更安全的第一步
很多相似查询或 API 调用N+1批量传 ID,预加载关联,或使用批量接口
互不依赖的调用时间相加串行 await只对独立工作使用 Promise.all
同一转换反复执行无意义重算按输入缓存,或把稳定初始化移出循环
行数增加后时间暴涨嵌套扫描先建一次 Map,或看查询计划后再加索引

这张表不能替代计时。它只是把计时结果转成最小补丁。只要修复会碰到安全、生产流量、计费或客户数据,就要停下来,在 fixture 之外执行前先让人批准。

还有一个判断顺序很有用:先看等待时间,再看重复次数,最后看算法复杂度。等待时间长,通常是数据库、网络或文件系统;重复次数多,通常是 N+1 或循环里的外部调用;数据量一大就突然变慢,才重点看二重循环、Map、索引和查询计划。这个顺序能让 Claude Code 的搜索路径更短,也能让审查者知道为什么先改这一处。

修复后不要马上删除计时代码。先保留到同一个测试命令通过,并把修改前后的表格贴到评审说明里。确认结束后,再把临时代码移除或改成正式日志。这样不会把调试输出长期留在生产路径里,也不会让团队失去这次判断的证据。

陷阱和修正

陷阱:没有命令就让 Claude Code “优化这个接口”。修正:先要求复现命令、fixture 和计时表,再允许重写。

陷阱:把合成数据结果当作生产基准。修正:明确本地数据是合成的,只用于定位可能瓶颈。生产结论必须来自自己系统里经过批准的观测数据。

陷阱:把串行循环直接换成无限制 Promise.all。修正:先确认任务互不依赖;如果访问数据库、付费 API 或有速率限制的服务,就加并发上限。

陷阱:因为慢路径里出现“数据库”就加索引。修正:查看查询计划,并写下读取收益、写入成本和存储成本。

Claude Code 的范围和人的批准

让 Claude Code 做可重复的工程工作:添加临时计时、创建合成 fixture、查找循环里的查询、提出批量读取方案、更新测试,并总结修复前后的证据。这些改动容易回滚,也容易审查。

把生产和业务风险留给人批准:认证、客户记录、把数据发给外部服务、提高付费 API 并发、修改计费限制、部署生产,以及任何 SLA 声明。代理可以准备差异和清单;风险决定由人负责。

清楚的交接句可以写成:“Claude 可以修改本地计时和测试。使用生产数据、改密钥、改计费控制或部署之前必须有人批准。”

主要 CTA

希望把这个流程变成团队习惯的读者,可以使用 Claude Code 培训与咨询页面。目标不是承诺神奇加速,而是建立可重复审查:命令、fixture、测得瓶颈、补丁和剩余风险都要留下。

动手验证

这次更新我检查了内部链接都使用 /zh/,外部链接指向 Node.js 官方文档,代码块包含可执行 JavaScript 和命令,示例只使用合成数据,CTA 指向中文培训页面。

我没有运行生产基准,没有查看真实客户事故,也没有声称某个线上服务已经提速。实际检查范围是文章内容、代码块语法形态、链接本地化,以及 Claude Code 可执行范围与人必须批准事项的分离。

读者在自己项目里复查时,可以只做三件事:确认 fixture 不含客户资料,确认命令能重复运行,确认修改前后的计时表使用同一份输入。只要其中一项不成立,就不要把结果写进发布说明或对外报告。先补齐输入和命令,再谈速度结论。

如果需要交给同事复审,请把命令、fixture 路径、修改文件、最慢区间和人工批准项放在同一段记录里。这样下一位维护者不用重新猜测上下文,也能判断这次加速是否只影响本地样例,还是已经准备好进入更严格的环境检查。

#claude-code #performance #optimization #prompt-engineering #productivity
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

让 Claude Code 真正进入可验证的工作流

先用免费 PDF 固定基础,再用 Gumroad 教材复用工作流;如果涉及团队导入、权限或收入路径,可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。