如何在存在依赖关系的pnpm工作区中正确运行watch脚本?
我的项目结构如下:
packages - alice - bar - foo package.json
其中alice、bar、foo是三个子包,bar是alice的依赖。每个子包的package.json里都定义了各自的watch脚本。
执行pnpm -r run watch时会卡住,因为watch脚本不会终止,pnpm会逐个等待命令执行完毕才会运行下一个。改成并行执行pnpm -r --parallel run watch后,首次执行仍会报错——bar还没构建完成,alice无法正确解析bar。
我看到有文章提到作者也遇到过相同问题,但没找到优雅的解决方案;另外注意到vitest用pnpm -r --parallel --filter=./packages/** run dev能正常运行,但不清楚原因。
1. 先全量构建再启动并行watch
先运行一次全量构建,确保所有依赖包的产物都已生成:
pnpm -r run build
之后再启动并行watch:
pnpm -r --parallel run watch
这种方式简单直接,首次启动前先保证所有产物存在,后续watch模式下子包更新会自动同步。
2. 分阶段启动watch脚本
先单独启动依赖包的watch并后台运行,等待几秒确保其完成首次构建后,再启动所有包的并行watch:
# 启动bar的watch并后台运行 pnpm --filter bar run watch & # 等待3秒确保bar完成首次构建,再启动全局并行watch sleep 3 && pnpm -r --parallel run watch
可以把这组命令封装到根目录package.json的脚本里:
{ "scripts": { "watch:start": "pnpm --filter bar run watch & sleep 3 && pnpm -r --parallel run watch" } }
之后直接执行pnpm watch:start即可。
3. 给watch脚本添加前置构建逻辑
修改每个子包的watch脚本,让它先执行一次完整构建,再进入监听模式。以TypeScript项目为例:
{ "scripts": { "watch": "tsc && tsc --watch" } }
这样即使并行启动,每个包都会先完成首次构建再监听变化,alice能等到bar的构建产物生成后再尝试解析。
关于vitest命令正常运行的原因
vitest的dev脚本本身会先完成首次测试环境初始化/构建,再进入监听模式;另外vitest可能依赖ESModule源码直接运行,不需要提前编译产物,或者自身具备依赖解析的容错机制,因此并行启动不会出现依赖未构建的问题。
内容的提问来源于stack exchange,提问作者Lynch

