前端安装包中的幽灵依赖

文章类型:node

发布者:hp

发布时间:2024-11-25

一:原因

在项目开发过程中,软件包可以依赖别的包,由此就产生了依赖图,

由于历史原因,nodeJs和npm采用不同的方式,

NPM使用真实软件包的文件夹副本来作为图的顶点,用子文件夹关系来表示图的边

NodeJs添加了一个特殊的解析规则,其效果就是引入额外的图边,也就是指向所有父文件夹的子文件夹

我们把这些没有在包的依赖中声明的定义,称为“幽灵依赖”

二:定义

幽灵依赖:是指在项目中使用了一些,没有被定义在其package.json文件中的包

{
  "name": "my-library",
  "version": "1.0.0",
  "main": "lib/index.js",
  "dependencies": {
    "minimatch": "^3.0.4"
  },
  "devDependencies": {
    "rimraf": "^2.6.2"
  }
}

三:形式

- my-monorepo/
  - package.json
  - node_modules/
    - semver/
    - ...
  - my-library/
    - package.json
    - lib/
      - index.js
    - node_modules/
      - brace-expansion
      - minimatch
      - ...

四:拓展

NPM采取的方案

1:每个项目都有自己的「node_modules 树」,树中包含了大量的包文件夹副本。

2:NPM 2.x,node_modules 文件夹树 很深 且 重复度高,但将 幽灵依赖 控制到了最少。

3:NPM 3.x 引入的安装算法会打平整个树,消除了大量的重复依赖,代价是引入了更多的 幽灵依赖 (额外的图边)

4:已安装的 「node_modules 树」不是独一无二的的。

五:缺点

1:不兼容的版本

2:丢失依赖问题

六:解决方案

采用pnpm安装包,把所有的包。存到一个仓库文件夹里面,然后在node_modules里面用正常的树结构,来表达包依赖

1:pnpm使用符号链接Symbolic link(软链接)来创建依赖项的嵌套结构,将项目的直接依赖符号链接到node_modules的根目录,直接依赖的实际位置在.pnpm/<name>@<version>/node_modules/<name>,依赖包中的每个文件再硬链接(Hard link)到.pnpm store。

2:.pnpm称为虚拟存储目录,以平铺的形式储存着所有的项目依赖包,每个依赖包都可以通过.pnpm/@/node_modules/路径找到实际位置。