每次安装默认链接一个隔离虚拟存储:直接依赖位于 node_modules 顶层,传递依赖链接到每机器存储中,未声明的(幻影)依赖失败而非意外解析。要获得普通的扁平 node_modules——npm 的布局,没有虚拟存储——在 .npmrc 中设置一行:

# .npmrc — 整个项目的扁平、npm 风格 node_modules
node-linker=hoisted

单次命令相同,无需触碰配置:

nub install --node-linker hoisted

这在每个现任包管理器下都工作——npm、pnpm、Yarn、Bun 和 Nub 身份项目——因为 node-linker 是 Nub 从 .npmrc 读取的中性键,无论哪个包管理器拥有项目。文件仍通过 reflink 或 hardlink 从全局内容存储物化,所以扁平树几乎不增加磁盘开销。

node-linker 是布局,不是提升模式

node-linker 设置选择布局:isolated(默认符号链接树)或 hoisted(扁平)。它与 hoistshamefully-hoistpublic-hoist-pattern 无关,这些在隔离布局内部将包提升到顶层。要扁平化树,使用 node-linker——提升模式保持虚拟存储不变。

按包管理器

每个包管理器有自己的扁平布局配置。Nub 遵守承载真实意图的那些建议,对其余的回退到中性 node-linker 键:

现任者其自身的扁平布局配置在 Nub 下
pnpm.npmrc 中的 node-linker=hoisted,或 pnpm-workspace.yaml 中的 nodeLinker: hoisted遵守——扁平树,无虚拟存储
npminstall-strategy=hoisted忽略——它是 npm 的默认值,所以不承载信号;设置 node-linker=hoisted
Yarn.yarnrc.yml 中的 nodeLinker: node-modules不作为布局请求读取;设置 node-linker=hoisted
Bun无——Bun 总是扁平物化设置 node-linker=hoisted
Nubnode-linker=hoisted遵守——扁平树,无虚拟存储

Nub 将包管理器兼容性限定到锁文件和依赖解析;安装布局是其自身的轴,默认为虚拟存储。所以现任者的布局配置仅在它是显式的、明确的选择时关闭虚拟存储——pnpm 的 node-linker,手动设置。中性 node-linker=hoisted 是唯一到处适用的杠杆。

扁平 vs 项目本地

两个设置关闭默认的不同部分,原因不同——按需选择:

# 扁平、npm 风格树 — 完全没有虚拟存储
node-linker=hoisted

# 保持隔离布局,但将存储移到项目内部
enableGlobalVirtualStore=false

enableGlobalVirtualStore=false 形式保持隔离及其幻影依赖保护;它只将存储从共享的每机器位置重定位到项目内部的 node_modules/.store/。这使树自包含——它在 Docker COPY --from 到新镜像时存活,共享存储不存在的地方。Nub 已在 CI 和 nub ci 下自动这样做,所以你很少手动设置。参见存储和磁盘布局了解共享 vs 项目本地存储的完整说明。