npm/yarn 依赖管理的对比

1,255 阅读4分钟

npm3以后的依赖管理

实现方法

npm 3 会遍历所有的节点,逐个将模块放在 node_modules 的第一层,当发现有重复模块时,则丢弃, 如果遇到某些依赖版本不兼容的问题,则继续采用 npm 2 的处理方式,前面的放在 node_modules 目录中,后面的放在依赖树中。举个🌰:A,B,依赖 D(v 0.0.1),C 依赖 D(v 0.0.2):

image.png

缺陷

但是 npm 3 会带来一个新的问题:由于在执行 npm install 的时候,按照 package.json 里依赖的顺序依次解析,上图如果 C 的顺序在 A,B 的前边,node_modules 树则会改变,会出现下边的情况: image.png

package-lock.json的出现

npm install 执行后,会生成一个 node_modules 树,在理想情况下, 希望对于同一个 package.json 总是生成完全相同 node_modules 树。在某些情况下,确实如此。但在多数情况下,npm 无法做到这一点。 对于同一个 package.json 无法总是生成完全相同 node_modules 树。 为了解决上述问题以及 npm 3 的问题,在 npm 5.0 版本后,npm install 后都会自动生成一个 package-lock.json 文件 ,当包中有 package-lock.json 文件时,npm install 执行时,如果 package.json 和 package-lock.json 中的版本兼容,会根据 package-lock.json 中的版本下载如果不兼容,将会根据 package.json 的版本,更新 package-lock.json 中的版本,已保证 package-lock.json 中的版本兼容 package.json。

pacakge-local.json的作用

  • 在团队开发中,确保每个团队成员安装的依赖版本是一致的,确定一棵唯一的 node_modules 树;
  • node_modules 目录本身是不会被提交到代码库的,但是 package-lock.json 可以提交到代码库,如果开发人员想要回溯到某一天的目录状态,只需要把 package.json 和 package-lock.json 这两个文件回退到那一天即可。
  • 由于 package-lock.json 和 node_modules 中的依赖嵌套完全一致,可以更加清楚的了解树的结构及其变化。
  • 在安装时,npm 会比较 node_modules 已有的包,和 package-lock.json 进行比较,如果重复的话,就跳过安装 ,从而优化了安装的过程。

yarn的依赖管理

安装依赖过程

image.png

  1. 「Checking」 在正式安装前,yarn会做一些check工作,会检查是否有npm的一些配置文件(Shrinkwrap,npm lockfile),如果有,会提示用户避免存在这些文件,可能会导致冲突。之后会去检查一些Manifest,包括os,cpu,engines,模块兼容等配置项。
  2. 「Resolving Packages」 解析包的信息,在这一步,会解析出依赖树中每个包的具体版本信息
  3. 「Fetching Packages」 获取依赖包,这一步,会对缓存中没有的包进行下载,将对应package下载到缓存目录下,完成这一步,代表着依赖树中需要的所有包都存在缓存当中了
  4. 「Linking Packages」 这一步,是将缓存中的对应包扁平化的安装到项目的依赖目录下(一般为node_modules
  5. 「Building Packages」 对于一些二进制包,需要进行编译,在此时进行

安装依赖算法: 同npm3的扁平化


npm2的依赖管理

实现方法:子依赖放在对应的父级包下面

npm 2 在安装依赖包时,采用简单的递归安装方法。执行 npm install 后,npm 根据 dependencies 和 devDependencies 属性中指定的包来确定第一层依赖,npm 2 会根据第一层依赖的子依赖,递归安装各个包到子依赖的 node_modules 中,直到子依赖不再依赖其他模块。执行完毕后,我们会看到 ./node_modules 这层目录中包含有我们 package.json 文件中所有的依赖包,而这些依赖包的子依赖包都安装在了自己的 node_modules 中 ,形成类似于下面的依赖树:

image.png

缺陷

当我的 A,B,C 三个包中有相同的依赖 D 时,执行 npm install 后,D 会被重复下载三次,而随着我们的项目越来越复杂,node_modules 中的依赖树也会越来越复杂,像 D 这样的包也会越来越多,造成了大量的冗余;在 windows 系统中,甚至会因为目录的层级太深导致文件的路径过长,触发文件路径不能超过 280 个字符的错误


参考文章:

  1. node_modules困境:mp.weixin.qq.com/s/GCfv-Hshw…
  2. 分析yarn的依赖机制:mp.weixin.qq.com/s/66fC_8a2J…
  3. 分析npm2.0、3.0的依赖机制: mp.weixin.qq.com/s/Vd745UW17…