无论使用 nvm 还是 fnm,每个 Node.js 版本通常都有独立的安装目录和全局 npm prefix。因此,在 Node.js 20 下全局安装的 CLI,不会自动出现在 Node.js 24 下。
fnm use 20
npm list --global --depth=0
fnm use 24
npm list --global --depth=0这种隔离不是缺陷。部分 npm 包包含原生扩展,会绑定特定 Node.js ABI;强制多个 Node.js 版本共享同一个全局目录,可能导致二进制不兼容或工具行为漂移。
项目工具优先本地安装
ESLint、Prettier、TypeScript、测试框架等工具应该进入项目依赖:
pnpm add --save-dev eslint prettier typescript然后通过项目脚本或 pnpm exec 调用:
pnpm exec eslint .
pnpm exec tsc --noEmitpnpm exec tsc 和 pnpm type-check 有什么区别
pnpm exec tsc --noEmit 会在项目作用域中执行 tsc。pnpm 会把 node_modules/.bin 加入这次命令的 PATH,因此通常实际使用的是当前项目依赖提供的 TypeScript CLI,而不是要求系统全局安装 tsc。
如果 package.json 已经定义:
{
"scripts": {
"type-check": "tsc --noEmit"
}
}那么 pnpm type-check 是 pnpm run type-check 的简写。pnpm 执行 scripts 时同样会把 node_modules/.bin 加入 PATH,所以脚本里的 tsc 可以直接被找到。
两者的区别主要在入口:pnpm exec tsc --noEmit 临时直接调用项目工具;pnpm type-check 调用项目约定好的脚本。项目已有标准脚本时优先使用脚本,这能统一本地开发与 CI 的参数。直接在普通 shell 中运行 tsc --noEmit 则依赖当前 shell 的 PATH,可能找不到命令或误用全局版本。
这样版本会被 package.json 和 lockfile 记录,开发机与 CI 更容易保持一致。
真正适合全局安装的是少量跨项目入口工具。迁移 Node.js 版本前,可先记录:
npm list --global --depth=0切换到新版本后只重装确实需要的工具。pnpm、Yarn 这类包管理器还可以交给 Corepack,避免在每个 Node.js 版本下手工维护一份全局安装。