主题
结论先行
在 Windows 上用 pnpm 装 VitePress 后如果构建时报:
text
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite' imported from
...\node_modules\vitepress\dist\node\chunk-xxxxxxxx.js不是没装 vite,是模块解析失败。 在项目根目录加一个 .npmrc:
ini
node-linker=hoisted删掉 node_modules 重新 pnpm install 即可。
为什么会这样
pnpm 默认用内容寻址 + 符号链接的布局:每个包的真实文件放在 node_modules/.pnpm/<pkg>@<ver>/node_modules/<pkg>,然后在需要它的位置创建一个 junction(Windows 上的目录符号链接)指过去。
这个设计本身很优雅——省磁盘、杜绝幽灵依赖。问题出在 Windows 上 junction 的解析路径上:Node 从 vitepress/dist/node/ 往上找 node_modules/vite 时,走到的是 junction 的字面路径而不是它指向的真实路径,于是找不到实际位于 .pnpm/vite@5.4.14/... 的那份 vite。
我在这个项目上验证过:
powershell
# junction 存在,目标也真实存在
vite -> LinkType=Junction Target=E:\...\.pnpm\vite@5.4.14\node_modules\vite Exists=True
# 但 Node 就是解析不到
PS> node -e "import('vite')"
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'vite'为什么选 hoisted 而不是别的办法
几个候选方案,以及我为什么没选它们:
| 方案 | 为什么不用 |
|---|---|
--preserve-symlinks | 要改 Node 启动参数,等于给所有命令都加一遍;而且它改变的是另一侧的行为,容易引入新的解析差异 |
| 手动 npm link vite | 治标,下次装依赖又坏;而且把问题藏起来了 |
| 换 npm / yarn | 能用,但放弃了 pnpm 的安装速度 |
node-linker=hoisted | 一次性配置写在 .npmrc 里,团队里每个人和 CI 都自动生效 |
hoisted 模式下 pnpm 退回到 npm 那样的扁平真实目录,不再有 junction,Windows 上的解析问题自然消失。代价是多占一点磁盘,对这个体量的项目完全可以忽略。
顺带一个坑:esbuild 的 postinstall 被拦
同一台机器上还遇到:
text
[ERR_PNPM_IGNORED_BUILDS] Ignored build scripts: esbuild@0.21.3pnpm 出于安全默认不执行依赖的 postinstall 脚本。esbuild 需要它来放置 native 二进制,没跑就可能构建失败。处理方式:
bash
pnpm approve-builds # 交互式,勾选 esbuild如果环境不允许交互,用 pnpm approve-builds --all,或者直接 pnpm rebuild esbuild。
值得记住的一句话
"找不到包"这类报错,先分清是"没装"还是"解析不到"。 前者看 lockfile 和安装日志,后者看 node_modules 的布局和解析规则。搞混了会在错误的方向上装一晚上依赖。