Open sufuwang opened 1 year ago
npm@2 的 node_modules
是嵌套存储的,npm 包的依赖存储于 npm 包的 node_modules
中,如果多个 npm 包依赖同一个 npm 包的话,这个 npm 包会被下载多次,若 npm 包的依赖很复杂,则嵌套的目录很深,Windows 系统路径的最大长度为 260 多个字符,在安装依赖的时候会出现意料之外的问题,并且 npm@2 没有 lock 文件固定 npm 包版本。简而言之,npm@2 的缺陷有:同一个依赖可能被多次安装,依赖嵌套,不能固定 npm 包版本
yarn 采用扁平化的安装结构和 yarn.lock
来解决上述问题,npm 包的依赖会被安装在项目的 node_modules
中,完美解决了上述两个问题,但引入了新的问题,被项目依赖的 npm 包会被安装到 node_modules
中,npm 包的依赖也会被安装到 node_modules
中,所以在项目中就可以引入一些不存在 dependencies
/ devDependencies
中,而这些不存在 dependencies
/ devDependencies
中,但存在于 node_modules
中的依赖,被称为幽灵依赖。需要注意的是,yarn 并不是完全不存在嵌套依赖的,当出现版本冲突的时候,yarn 是会采取嵌套依赖来解决的。简而言之,yarn 的缺陷有:解决版本冲突时,同一个依赖可能被多次安装,以及幽灵依赖
npm@3 和 yarn 的安装原理已经一致,且使用了 package-lock
pnpm 会把 npm 包存储到 .pnpm store 中,即根目录下 node_modules/.pnpm,项目下的 node_modules/.pnpm 使用 hard link
或 symbolic link
去链接资源,第一次链接包 a 时,使用 hard link
,后续如果再次使用到 a 时,使用 symbolic link
链接到之前的 hard link
,这是 node_modules/.pnpm 的逻辑,对于 node_modules/!.pnpm 则为项目的 dependencies
/ devDependencies
依赖,而这些文件夹则一定是对于 node_modules/.pnpm 下文件夹的 symbolic link
npm & yarn 中只需在根目录下的 package.json
添加 Workspace 的地址即可
"workspaces": [
"apps/*"
],
这两种 Manager 会做两件事情
这会放大幽灵依赖的缺点,前面提到的幽灵依赖只是针对第三方 npm 包,而这里还包括对 Workspace 的幽灵依赖。优点显而易见,这种管理方式可以减少硬盘存储、安装耗时
pnpm 不支持使用 package.json
> Workspace 来定义,而是使用 pnpm-workspace.yaml
packages:
- "apps/*"
pnpm 会严格按照目录下的 package.json
来安装依赖,避免了幽灵依赖,但安装耗时趋向最大,所以 pnpm 支持 .npmrc
文件来优化,比如对于共用的依赖,可以使用这个文件来提升到根目录下的 node_modules 文件夹,当然还有其他功能
pnpm 需要在 package.json
指定依赖的其他 Workspace
"dependencies": {
"appa": "workspace:*",
"appb": "workspace:*"
}
npm & yarn 调用 Workspace 的 scripts
的 Command 是相同的
npm run dev --workspaces
npm run dev --workspace=main
pnpm 使用另一种
pnpm -F main dev
pnpm --filter main dev
pnpm -F '*' dev
pnpm -F '!main' -F '!other' dev
require 的原理
使用 require 引入一个 npm 包,存在这几种情况
找到目标文件之后,以 commonjs 为例,require 的原理如以下伪代码所示