pnpm 项目里用 pnpm why 看依赖是谁带进来的

32 次浏览5 条回复

排查 node_modules 里某个包为什么会出现时,pnpm why 比直接翻 lockfile 省点眼睛。

环境:Node.js 18+,pnpm 8+。可以在临时目录试一下:

mkdir pnpm-why-demo && cd pnpm-why-demo
pnpm init
pnpm add vite @vitejs/plugin-react
pnpm why esbuild

输出会列出 esbuild 是被哪些依赖链带进来的,也能看到当前解析到的版本。想看开发依赖里的来源,默认也会一起显示;如果仓库比较大,可以加包名精确查,不要直接扫一整页 lockfile。

这个命令只读取依赖图,不会改 package.json 或 lockfile。升级依赖前发现某个包版本不对,先跑一下挺顺手。

这个命令在 monorepo 里也挺好用,尤其是怀疑某个包被 workspace 里的工具链间接带进来时。想再缩小范围可以试试 pnpm why esbuild --parseable,输出更适合丢给脚本处理。只是它反映的是当前 lockfile 和安装状态,改完依赖后最好重新跑一次。

补一个小点:如果只是排查线上包体或生产依赖,可以加 --prod 缩一下范围:

pnpm why esbuild --prod

这样 devDependencies 里的链路不会混进来,结果会清爽一点。反过来只想看开发依赖时也可以用 --dev。

大项目里输出太长的话,还可以先加个 --depth 控制展开层级,比如:

pnpm why esbuild --depth 1

先看是哪几个直接依赖方向带进来的,再把深度调大追细链路。这样比一上来铺满整屏依赖树好读一点。

monorepo 里如果只关心某个子包,也可以把过滤器放在前面跑:

pnpm --filter ./packages/web why esbuild

这样结果只按这个 workspace 的依赖关系算,不容易被别的 app 或工具包带偏。包名稳定的话也可以用 --filter web,不过路径选择器通常更直观一点。

如果是在 workspace 根目录想先扫一遍所有子项目,可以用 recursive 方式:

pnpm -r why esbuild

它会按不同 importer 分开列结果,适合先判断到底是哪几个包在引入。范围太大再配合楼上说的 --filter 缩回单个 package,看起来会舒服很多。