Nodejs
包管理器
npm/pnpm/yarn 的差异
安装命令
npm i packagepnpm add packageyarn add package运行命令
npm run devpnpm devyarn dev依赖处理
考虑下面这种情况
-
element-plus是个基于vue3的npm包, 他依赖了dayjs -
当你使用三种包管理器方式下载
element-plus
npm i element-pluspnpm add element-plusyarn add element-plus- 使用
element-plus
import ElementPlus from "element-plus"- 使用
dayjs你发现你的项目也需要使用dayjs包, 恰恰这个时候你又发现了element-plus依赖了dayjs。
于是你直接使用import dayjs from 'dayjs'
神奇的事情发生了, npm 和 yarn(v1) 均可以正常工作, 但是 pnpm 和 yarn(v2) 都炸了
Cannot find module 'dayjs' or its corresponding type declarations.ts(2307)为什么会出现这种情况呢?
依赖扁平化 vs 严格隔离
- npm 的做法 (扁平化)
npm安装时,会将所有依赖扁平化地安装在项目根目录的node_modules里。- 所以即使你没显式安装
dayjs, 只要它是element-plus的依赖,就会被放在根目录的node_modules, 你也能直接import dayjs。 - 这其实是依赖穿透,是 Node.js 的模块解析机制默认支持的,但并不推荐依赖这一特性。
- pnpm 的做法 (严格的隔离依赖)
pnpm使用所谓的 内容寻址Content Addressable和硬链接的结构,并且默认遵守模块隔离 原则。- 它只会将你的直接依赖暴露在顶层
node_modules。 element-plus的依赖(即 dayjs)被安装在element-plus的node_modules下,你项目的代码无法直接访问。- 所以:如果你想直接
import dayjs,你必须把dayjs加到你的dependencies中。
- yarn 的行为
- Yarn v1 类似于 npm, 默认也会扁平化依赖,所以一般可以访问
element-plus的依赖dayjs。 - Yarn Berry (v2+) 更像 pnpm, 引入了
Plug'n'Play(PnP)机制,完全不使用node_modules,而是基于.pnp.js映射,更加严格,不允许穿透依赖。