“ npm install”和“ npm ci”有什么区别?


215

我正在进行持续集成,并发现了npm ci命令。

我不知道在我的工作流程中使用此命令有什么好处。

它更快吗?它会使测试变得更困难,更好以及之后吗?

Answers:


327

npm docs中

简而言之,使用npm install和npm ci之间的主要区别是:

  • 该项目必须具有现有的package-lock.json或npm-shrinkwrap.json。
  • 如果程序包锁中的依赖项与package.json中的依赖项不匹配,则npm ci将退出并显示错误,而不是更新程序包锁。
  • npm ci一次只能安装整个项目:此命令不能添加单个依赖项。
  • 如果已经存在node_modules,它将在npm ci开始安装之前自动删除。
  • 它永远不会写入package.json或任何包锁:安装实际上是冻结的。

本质上, npm install读取package.json会创建依赖项列表,并用于package-lock.json告知要安装这些依赖项的版本。如果不存在依赖项package-lock.json,则将添加npm install

npm ci(以C intinuous I ntegration 命名)直接从中安装依赖项,package-lock.json并且package.json仅用于验证没有不匹配的版本。如果缺少任何依赖项或版本不兼容,它将抛出错误

使用npm install到一个项目中添加新的依赖,并更新相关的更新。通常,在拉动更新依赖项列表的更改之后,您将在开发期间使用它,但是npm ci在这种情况下使用它可能是一个好主意。

使用npm ci如果你需要一个确定的,可重复的构建。例如,在持续集成,自动化作业等过程中,以及在首次安装依赖项时,而不是npm install

npm install

  • 安装软件包及其所有依赖项。
  • 依赖关系由npm-shrinkwrap.jsonpackage-lock.json(按此顺序)驱动。
  • 不带参数:安装本地模块的依赖项。
  • 可以安装全局软件包。
  • 将在中安装所有缺少的依赖项node_modules
  • 它可能会写入package.jsonpackage-lock.json
    • 与参数(npm i packagename)结合使用时,它可能会写入package.json以添加或更新依赖项。
    • 当不带参数使用时,(npm i)可能会写入以package-lock.json锁定某些依赖项的版本(如果它们尚未在此文件中)。

npm ci

  • 至少需要npm v5.7.1
  • 需要package-lock.jsonnpm-shrinkwrap.json存在。
  • 如果这两个文件的依赖项不匹配,则会引发错误package.json
  • 一次删除node_modules并安装所有依赖项
  • 它从不写入package.jsonpackage-lock.json

算法

npm ci从生成整个依赖树package-lock.jsonnpm-shrinkwrap.jsonnpm install 更新的内容node_modules使用以下算法():

load the existing node_modules tree from disk
clone the tree
fetch the package.json and assorted metadata and add it to the clone
walk the clone and add any missing dependencies
  dependencies will be added as close to the top as is possible
  without breaking any other modules
compare the original tree with the cloned tree and make a list of
actions to take to convert one to the other
execute all of the actions, deepest first
  kinds of actions are install, update, remove and move

1
我不知道npm install可以写package.json。你知道它会写在这里吗?
Veve

5
好吧,这可能会引起误解...当您使用它来安装,更新或删除依赖项时,它将写入package.json。我会在文字中更清楚地说明,谢谢!
lucascaro

该算法在哪里记录?即您的来源是什么?
Yngvar Kristiansen

1
@YngvarKristiansen在npm文档中,添加了指向特定部分的链接以供参考
lucascaro

4
npm install package可以同时修改package-lock.json package.json,而没有npm install参数只能修改package-lock.json
旋钮

20

npm ci将删除任何现有的node_modules文件夹,并依靠该package-lock.json文件来安装每个软件包的特定版本。它比npm install快得多,因为它跳过了某些功能。干净的状态安装非常适合ci / cd管道和docker构建!您还可以使用它一次安装所有内容,而不是特定的软件包。


9

您链接的文档具有以下摘要:

简而言之,使用npm install和npm ci之间的主要区别是:

  • 该项目必须具有现有的package-lock.json或npm-shrinkwrap.json。
  • 如果程序包锁中的依赖项与package.json中的依赖项不匹配,则npm ci将退出并显示错误,而不是更新程序包锁。
  • npm ci一次只能安装整个项目:此命令不能添加单个依赖项。
  • 如果已经存在node_modules,它将在npm ci开始安装之前自动删除。
  • 它永远不会写入package.json或任何包锁:安装实际上是冻结的。

2

这些命令在功能上非常相似,但是区别在于安装您的package.jsonpackage-lock.json文件中指定的依赖项所采用的方法不同。

npm ci对应用程序的所有依赖项执行全新安装,而npm install如果系统上已存在某些安装,则可以跳过某些安装。如果系统上已经安装的版本不是您package.json要安装的版本,则可能会出现问题,即安装的版本与“ required ”版本不同。

其他区别将是npm ci永远不会触碰您的package*.json文件。如果依赖版本与package.jsonpackage-lock.json文件中的不匹配,它将停止安装并显示错误。

您可以从此处的官方文档中获得更好的解释。

此外,您可能想在此处阅读有关包锁的信息


1

值得记住的是,像alpine这样的轻型节点docker映像没有安装Python,而Python node-gyp使用的依赖项npm ci

我认为,为了能够npm ci正常工作,您需要在构建中安装Python作为依赖项。

在此处了解更多信息Docker和npm-gyp ERR!不好


0

尽管其他所有人都回答了技术差异,但没有人解释在哪种情况下都应使用两种情况。

您应该在不同的情况下使用它们。

npm install当您要缓存node_modules目录时,对于开发和CI来说非常有用。什么时候使用?如果要打包供其他人使用(不包括node_modules在此发行版中),则可以执行此操作。关于缓存,请注意,如果您计划支持不同版本的Node.js记住,node_modules由于Node.js运行时要求之间的差异,可能必须重新安装该版本。如果您希望使用一个版本,请使用最新版本LTS

npm ci当您要测试和发布生产应用程序(最终产品,不要被其他软件包使用)时,应使用此方法,因为使安装尽可能具有确定性很重要,此安装将花费更长的时间,但最终会使您的应用程序更可靠(您确实包含node_modules在此发行版中)。坚持使用的LTS版本Node.js

奖励:您可以根据要制作的复杂程度来混合使用它们。在功能分支中,git您可以缓存,node_modules以提高团队的工作效率;在合并请求时,主分支也可以依靠此npm ci来获得确定的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.