npm

1. 原理

1. 检查.npmrc文件, 优先级为:项目级的.npmrc 文件 > 用户级的.npmrc 文件> 全局级的.npmrc文件 > npm内置的.npmrc 文件 2. 检查有无lock文件 3. 无lock文件 1. 从npm远程获取包信息 2. 根据package.json构建依赖树 3. 在缓存中依此查找依赖树中每个包 1. 不存在缓存: 1. 从npm包远程仓库下载包 2. 检查包的完整性 3. 检查不通过就重新下载 4. 检查通过 1. 将下载的包复制到npm缓存目录 2. 将下载的包依照依赖树结构解压到node_modules 2. 存在缓存:将缓存按照依赖结构解压到 node_modules 4. 将包解压到 node_modules 5. 生成lock文件 4. 有lock文件 1. 检查package.json中依赖版本和是否和package-lock.json中的依赖有冲突 2. 如果没有冲突,直接跳过获取包的、构建依赖树、查找缓存后续过程相同

1. 项目代码中引用了一个模块,模块查找流程如下

  1. 在当前模块路径下搜索
  2. 在当前模块 node_modules 路径下搜素
  3. 在上级模块的 node_modules 路径下搜索
  4. 直到搜索到全局路径中的 node_modules

2. npm 3.x 新增扁平结构

  1. 安装模块时,不管其是直接依赖还是子依赖的依赖,优先将其安装在node_modules根目录;当安装到相同模块时,判断已安装的模块版本是否符合新模块的版本范围,如果符合则跳过,如果不符合则在当前模块的node_modules下安装该模块。
  2. 解决了
  3. 不同层级的依赖中, 可能引用同一个模块, 导致大量冗余
  4. 在windows系统中,文件路径最大长度为260个字符,嵌套过深可能导致不可预祝的问题

2. 缺点

  1. 没有彻底解决扁平结构
    1. 如果依赖的不同版本的包依然会存在嵌套问题

yarn

1. 原理

1. **A、检查(checking):**主要是检查项目中是否存在一些 npm 相关的配置文件,如 package-lock.json 等。如果存在,可能会警告提示,因为它们可能会存在冲突。在这一阶段,也会检查系统 OS、CPU 等信息。 2. **B、解析包(resolving packages):** 在经过复杂的解析算法后,我们就确定了所有依赖的具体版本信息以及下载地址 1. 首先获取项目 package.json 中声明的首层依赖,包括 dependencies, devDependencies, optionalDependencies 声明的依赖 2. 接着采用遍历首层依赖的方式获取依赖包的版本信息,以及递归查找每个依赖下嵌套依赖的版本信息,并将解析过和正在解析的包用一个 Set 数据结构来存储,这样就能保证同一个版本范围内的包不会被重复解析 3. **C、获取包(fetching packages):** 这一步主要是利用系统缓存,到缓存中找到具体的包资源(查看缓存:yarn cache dir) 1. 首先会尝试在缓存中查找依赖包,如果没有命中缓存,则将依赖包下载到缓存中。(判断系统中存在符合 "cachefolder+slug+node_modules+pkg.name" 规则的路径) 2. 对于没有命中缓存的包,Yarn 会维护一个 fetch 队列,按照规则进行网络请求。这里也是 yarn 诞生之初解决 npm v3 安装缓慢问题的优化点,**支持并行下载** 4. **D、链接包(linking dependencies:** 这一步主要是将缓存中的依赖,复制到项目目录下,同时遵循扁平化原则 5. **F、构建包(building fresh packages):** 如果依赖包中存在二进制包需要进行编译,会在这一步进行。

2. yarn和npm区别

  1. lockfile。package-lock.json 自带版本锁定+依赖结构,你想改动一些依赖,可能影响的范围要比表面看起来的复杂的多;而 yarn.lock 自带版本锁定,并没有确定的依赖结构,使用 yarn 管理项目依赖,需要 package.json + yarn.lock 共同确定依赖的结构
  2. 依赖管理策略
  3. 性能, yarn性能在有缓存、重新install的情况下会比npm好不少

pnpm

1. 特点

  1. 包安装速度极快
  2. 磁盘空间利用非常高效
  3. 支持 monorepo
    之前对于多个项目的管理,我们一般都是使用多个 git 仓库,但 monorepo 的宗旨就是用一个 git 仓库来管理多个子项目,所有的子项目都存放在根目录的packages目录下,那么一个子项目就代表一个package
  4. 安全性更高

2. 原理

1. 速度快

在绝多大数场景下,pnpm包安装的速度都是明显优于npm/yarn,速度会比 npm/yarn快2-3倍

  1. yarn PnP:直接去掉 node_modules,将依赖包内容写在磁盘,节省了 node 文件 I/O 的开销,这样也能提升安装速度。(具体原理见这篇文章https://loveky.github.io/2019/02/11/yarn-pnp/)

2. 存储管理

a. 基于内容寻址的文件系统来存储磁盘上所有的文件

  1. 不会重复安装同一个包: 如果 100 个项目都依赖 lodash,那么 lodash 很可能就被安装了 100 次,磁盘中就有 100 个地方写入了这部分代码, 使用 pnpm 只会安装一次,磁盘中只有一个地方写入
  2. 即使一个包的不同版本,pnpm 也会极大程度地复用之前版本的代码:比如 lodash 有 100 个文件,更新版本之后多了一个文件,那么磁盘当中并不会重新写入 101 个文件,而是保留原来的 100 个文件的 hardlink,仅仅写入那一个新增的文件

3. 依赖管理

4. 安全管理

3. 日常使用

  1. pnpm install
  2. pnpm update
  3. pnpm uninstall
1
2
3
// 移除 axios 
// --filter 来指定 package。
pnpm uninstall axios --filter package-a
  1. pnpm link
1
2
// 将本地项目连接到另一个项目。注意,使用的是硬链接,而不是软链
pnpm link ../../axios

文章来源

文章来源

文章来源