yarn和npm的区别

发布时间 2023-06-27 14:34:57作者: 脏猫

Yarn 是什么?

yarn 是为弥补 npm 的一些缺陷而出现的用以代替 npm 的 js 包管理工具。

npm 的一些人尽皆知的不足:

  • npm install的时候巨慢。特别是新的项目拉下来要等半天,删除 node_modules,重新 install 的时候依旧如此。
  • 同一个项目,安装的时候无法保持一致性。由于 package.json 文件中版本号的特点,下面三个版本号在安装的时候代表不同的含义。
"5.0.3",
"~5.0.3",
"^5.0.3"

“5.0.3”表示安装指定的 5.0.3 版本,“~ 5.0.3”表示安装 5.0.X 中最新的版本,“^5.0.3”表示安装 5.X.X 中最新的版本。这就麻烦了,常常会出现同一个项目,有的同事是 OK 的,有的同事会由于安装的版本不一致出现 bug。

  • 安装的时候,包会在同一时间下载和安装,中途某个时候,一个包抛出了一个错误,但是 npm 会继续下载和安装包。因为 npm 会把所有的日志输出到终端,有关错误包的错误信息就会在一大堆 npm 打印的警告中丢失掉,并且你甚至永远不会注意到实际发生的错误

Yarn 的优点

  • 速度快 。速度快主要来自以下两个方面:
  1. 并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。
  2. 离线模式:如果之前已经安装过一个软件包,用 Yarn 再次安装时之间从缓存中获取,就不用像 npm 那样再从网络下载了。
  • 模块扁平化安装,安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。

    一或多个具有相同版本范围的依赖声明,确定一个可用的版本。这就是 lockfile 的确定性。

    如果同一个依赖存在多个版本,那么最高版本安装在顶层目录,即 node_modules 目录。

  • 更简洁的输出:npm 的输出信息比较冗长。在执行 npm install<package> 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji 直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。

  • 多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。

  • 更好的语义化: yarn 改变了一些 npm 命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。

npm(v6) vs yarn(v1)

相同点:

  1. package.json 作为项目依赖描述文件。
  2. node_modules 作为依赖存储目录,yarn v2 不再是这样。
  3. lockfile 锁定版本依赖,在 yarn 中叫 yarn.lock,在 npm 中叫 package-lock.json,在 npm v7 也支持了 yarn.lock。它确保在不同机器或不同环境中,能够得到稳定的 node_modules 目录结构。

差异:

  1. 依赖管理策略。
  2. lockfile。package-lock.json 自带版本锁定+依赖结构,你想改动一些依赖,可能影响的范围要比表面看起来的复杂的多;而 yarn.lock 自带版本锁定,并没有确定的依赖结构,使用 yarn 管理项目依赖,需要 package.json + yarn.lock 共同确定依赖的结构。
  3. 性能。(对比 npm v6 和 yarn v1)目前 npm v7 优化了缓存和下载网络策略,性能的差异在缩小。

回答此前的疑问

Q:项目依赖出现问题怎么办?删了重装,即先删除 node_modules 再重新 install,那这样的操作会不会存在风险?

A:一般没有问题,如果有 lock 文件,根据 lock 的确定的版本重新安装可能仍然会导致问题,这种时候可以试着删掉 lock 文件。

Q:把所有依赖都安装到 dependencies 中,不区分 devDependencies 会有问题吗?

A:dev 对应开发环境,有些包比如 webpack、glup 还有性能检测工具啥的不需要在生产环境上用就写入 devdependence。

Q:我们的应用依赖了 pkg-a 和 pkg-b,同时 pkg-a 也依赖了 pkg-b,那么 pkg-b 会被多次安装或重复打包吗?

A:npm(v3)根据先来后到安装依赖在根目录,之后安装依赖要再用到这个依赖不必再装,但是如果版本不同就会在该依赖下的 node_modules 里再安装一次。不同版本的出场顺序导致依赖结构的差异,所以 npm v3 注定不是稳定的包管理工具。

Q:一个项目中,我使用 npm 别人使用 yarn,这会引发什么问题?

A: 可能根据两者的 lockfile 的不同,即安装版本不同最终可能会导致些兼容问题。

Q: 我们是否要提交 lockfile(package-lock.json/yarn.lock) 到项目仓库呢?

A: 要的,lockfile 确定了安装的版本,在后续开发上可以避免很多问题。

Q: lockfile 在 git 操作时,时常会出现大量的冲突,你是怎么解决的呢?

A: 如果 yarn.lock 在代码合并的过程中出现了问题,可以尝试使用 yarn install 解决问题。