`pnpm dev` in `packages/nodes-base` fails with `Cannot find module ‘@utils/…’` (tsc-watch hook ignores `&&`)

在 packages/nodes-base 下执行 pnpm dev 时, tsc-watch 的 --onCompilationComplete 钩子不能识别 && ,导致 tsc-alias 没有执行,编译产物里保留 @utils/... 路径别名,后续生成元数据时报 Cannot find m

快速结论:在 packages/nodes-base 下执行 pnpm dev 时,tsc-watch 的 --onCompilationComplete 钩子不能识别 &&,导致 tsc-alias 没有执行,编译产物里保留 @utils/... 路径别名,后续生成元数据时报 Cannot find module '@utils/query-escaping';优先排查 watch 脚本中钩子命令链的写法。

适用环境:Issue 中确认的环境为 n8n 仓库 master 分支、macOS、pnpm 工作区;报错涉及 packages/nodes-base、tsc-watch(已检查 6.2.0 与 7.2.1 的 dist/lib/runner.js)、tsc-alias 与 n8n-generate-metadata。TypeScript 版本方面,Issue 提到 pnpm build 使用 7.0.2、tsc-watch 使用 6.0.2,但明确说明未验证这是否为诱因。

最快修复方案:Issue 作者已验证:把全部步骤合并到一个 --onSuccess 的 sh -c 链中执行,如 tsc-watch -p tsconfig.build.cjs.json --onSuccess "sh -c 'pnpm copy-nodes-json && tsc-alias -p tsconfig.build.cjs.json && pnpm n8n-generate-metadata'";评论确认该修复有效。

注意事项:仅把钩子包进 sh -c 但保留两个钩子的写法并不可靠:Issue 作者测试时 tsc-alias 虽然运行了,n8n-generate-metadata 仍因别名未解析而崩溃,推测(作者未读调度代码)是 --onSuccess 与 --onCompilationComplete 同时启动所致;另外,失败后 dist 中的坏文件会保留,需先修复再重启。

问题场景

按 CONTRIBUTING.md 的“Selective Package Development”示例,在 packages/nodes-base 下运行 pnpm dev 进行本地开发编译。首次编译完成(日志显示“Found 0 errors”)后,监听进程在生成元数据阶段崩溃。以下场景也可能触发:启动时 dist 不存在;启动时有源文件比 dist 新(如刚 git pull);监听期间节点文件发生变更。

报错原文

$ node scripts/copy-nodes-json.js . '&&' tsc-alias -p tsconfig.build.cjs.json

Error: Cannot find module '@utils/query-escaping'
Require stack:
- .../packages/nodes-base/dist/nodes/Aws/Cognito/descriptions/user/getAll.operation.js
...
- .../packages/core/bin/generate-metadata
  code: 'MODULE_NOT_FOUND'

原因分析

原 watch 脚本为:tsc-watch -p tsconfig.build.cjs.json --onCompilationComplete "pnpm copy-nodes-json && tsc-alias -p tsconfig.build.cjs.json" --onSuccess "pnpm n8n-generate-metadata"。tsc-watch 不通过 shell 启动钩子,而是用 string-argv 拆分字符串、再用 cross-spawn 启动,因此 && 被当成普通参数传给 copy-nodes-json.js(日志中可见 '&&'),tsc-alias 实际未执行,dist 中编译文件仍保留 @utils/... 别名。随后 n8n-generate-metadata 加载这些编译节点时找不到对应模块,抛出 MODULE_NOT_FOUND。该 && 链由提交 d754ce922d(#16884)在构建切回 tsc-watch 时引入。另据 Issue 作者观察,钩子并行调度可能让元数据步骤在 tsc-alias 重写文件之前读取产物,此为可能原因,作者未核实调度实现。

环境排查

  • 确认所在分支为 master,并已在仓库根目录完成 pnpm install 和 pnpm build。
  • 确认 packages/nodes-base/package.json 中 watch 脚本仍是旧写法,即 --onCompilationComplete 钩子内含 &&。
  • 检查 packages/nodes-base/dist 中编译产物是否残留未解析的 @utils/... require;Issue 作者在失败后曾观察到 314 个此类文件。
  • 确认 tsc-watch 与 TypeScript 版本(Issue 中为 tsc-watch 6.2.0 / 7.2.1,TypeScript 6.0.2 / 7.0.2),该差异未被证实为诱因,仅作记录。
  • 确认 sh 在当前环境中可用(修复方案依赖 sh -c),Issue 已验证环境为 macOS。

解决步骤

  1. 按 Issue 复现路径定位问题:在仓库根目录执行 pnpm install、pnpm build,然后 cd packages/nodes-base && pnpm dev,观察日志中是否出现 '&&' 被当作参数传给 copy-nodes-json.js。
  2. 修改 packages/nodes-base/package.json 中的 watch 脚本,把所有步骤放进同一个 --onSuccess 的 sh -c 链中,顺序为 copy-nodes-json → tsc-alias → n8n-generate-metadata,即 "watch": "tsc-watch -p tsconfig.build.cjs.json --onSuccess \"sh -c 'pnpm copy-nodes-json && tsc-alias -p tsconfig.build.cjs.json && pnpm n8n-generate-metadata'\""。
  3. 若此前已有失败运行,先在 packages/nodes-base 下执行 pnpm exec tsc-alias -p tsconfig.build.cjs.json 修复 dist 中残留的别名,再重新启动。
  4. 重新执行 pnpm dev,确认编译完成后别名已解析、元数据生成成功,并进入持续监听状态。

验证方法

在 packages/nodes-base 下运行 pnpm dev,编译完成后日志中不应再出现 '&&' 作为参数传给脚本的行,也不应出现 Cannot find module '@utils/query-escaping'。可抽查 dist 中的编译文件确认 @utils/... 已重写为相对路径,并确认元数据生成步骤正常结束、监听进程保持运行。Issue 评论中报告者已确认修复后可用。

参考来源

n8n-io/n8n #42857

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 32000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注