从 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
(也称为 Clean Install)旨在用于自动化环境,例如测试平台、持续集成、和部署——或者,任何你想确保你对依赖项进行干净安装的情况。
它直接从 package-lock.json
安装依赖项,并仅使用 package.json
来验证没有不匹配的版本。 如果缺少任何依赖项或版本不兼容,则会引发错误。
使用 npm install
添加新的依赖项,并更新项目的依赖项。通常,您会在拉取更新依赖列表的更改之后在开发期间使用它,但在这种情况下使用 npm ci
可能是个好主意。
如果您需要确定性、可重复的构建,请使用 npm ci
。例如,在持续集成、自动化作业等期间以及第一次安装依赖项时,而不是 npm install
。
npm 安装
安装包及其所有依赖项。
依赖项由 npm-shrinkwrap.json 和 package-lock.json 驱动(按此顺序)。
不带参数:安装本地模块的依赖项。
可以安装全局包。
将在 node_modules 中安装任何缺少的依赖项。
它可能会写入 package.json 或 package-lock.json。当与参数(npm i packagename)一起使用时,它可能会写入 package.json 以添加或更新依赖项。当不带参数使用时,(npm i)它可能会写入 package-lock.json 以锁定某些依赖项的版本(如果它们不在此文件中)。
当与参数(npm i packagename)一起使用时,它可能会写入 package.json 以添加或更新依赖项。
当不带参数使用时,(npm i)它可能会写入 package-lock.json 以锁定某些依赖项的版本(如果它们不在此文件中)。
npm ci
至少需要 npm v5.7.1。
需要存在 package-lock.json 或 npm-shrinkwrap.json。
如果这两个文件的依赖项与 package.json 不匹配,则会引发错误。
删除 node_modules 并立即安装所有依赖项。
它从不写入 package.json 或 package-lock.json。
算法
当 npm ci
从 package-lock.json
或 npm-shrinkwrap.json
生成整个依赖关系树时,npm install
使用以下算法 (source) 更新 node_modules
的内容:
从磁盘加载现有的 node_modules 树具有克隆树的原始树并列出将一个转换为另一个要执行的所有操作,最深的第一类操作是安装、更新、删除和移动
npm ci
将删除任何现有的 node_modules
文件夹并依赖 package-lock.json
文件来安装每个软件包的特定版本。它比 npm install 快得多,因为它跳过了一些功能。它的干净状态安装非常适合 ci/cd 管道和 docker 构建!您还可以使用它一次安装所有内容,而不是特定软件包。
虽然其他人都回答了技术差异,但没有人解释在什么情况下使用两者。
您应该在不同的情况下使用它们。
当您想要缓存 node_modules
目录时,npm install
非常适合开发和 CI。什么时候用这个?如果您正在制作一个包供其他人使用,则可以这样做(您在这样的版本中不包括 node_modules
)。关于缓存,请注意,如果您计划支持不同版本的 Node.js
,请记住,由于 Node.js
运行时要求之间的差异,可能必须重新安装 node_modules
。如果您想坚持使用一个版本,请坚持使用最新的 LTS
。
当您要测试和发布生产应用程序(最终产品,不被其他软件包使用)时,应该使用 npm ci
,因为重要的是让安装尽可能具有确定性,此安装将花费更长的时间,但最终将使您的应用程序更可靠(您确实在这样的版本中包含 node_modules
)。坚持使用 Node.js
的 LTS
版本。
npm i
和 npm ci
都使用 npm 缓存(如果存在),此缓存通常位于 ~/.npm
。
此外,npm ci
尊重 package-lock.json
文件。与 npm install
不同,它重写文件并始终安装新版本。
奖励:您可以根据自己的复杂程度混合它们。在 git
中的功能分支上,您可以缓存 node_modules
以提高团队的工作效率,而在合并请求和主分支上,则依赖 npm ci
来获得确定性结果。
npm i
而不是 npm ci
,除非您要更新依赖项。 npm ci
总是更好,因为确定性行为总是更好
npm i
缓存速度更快,而 npm ci
速度较慢,因为它会进行完全重新安装。它们都很有用。
npm ci
也一样快
npm ci
即使在使用本地 NPM 缓存重复执行时也会明显变慢:npm install
大约为 2 秒,npm ci
为同一项目运行时为 16 秒。清除缓存后,它们是相同的。我们迫切需要可以从 package-lock 安装但不要从删除 node_modules 开始的东西:github.com/npm/cli/issues/564
node_modules
是一项功能,因为我已经看到开发人员在其中进行了一些自定义更改,并且想知道为什么它不适用于生产。我总是更喜欢一个具有重复完全相同结果的命令,而不是看似更快的命令。然而,npm install
可能会改变 package-lock.json
的事实对于依赖管理器来说是一个非常糟糕的默认设置,并且对于 npm ci
来说也是一个巨大的胜利。即使在我的开发机器上,我也总是使用 ci
进行纯安装,并且仅当我想更新或添加新的依赖项时才使用 install
。
您链接的文档有摘要:
简而言之,使用 npm install 和 npm ci 的主要区别是: 项目必须有一个现有的 package-lock.json 或 npm-shrinkwrap.json。如果包锁中的依赖项与 package.json 中的依赖项不匹配,npm ci 将退出并报错,而不是更新包锁。 npm ci 一次只能安装整个项目:无法使用此命令添加单个依赖项。如果 node_modules 已经存在,它将在 npm ci 开始安装之前自动删除。它永远不会写入 package.json 或任何包锁:安装基本上是冻结的。
这些命令在功能上非常相似,但不同之处在于安装 package.json
和 package-lock.json
文件中指定的依赖项所采用的方法。
npm ci
对您的应用程序的所有依赖项执行全新安装,而 npm install
可能会跳过一些安装,如果它们已经存在于系统中。如果系统上已安装的版本不是您的 package.json
打算安装的版本,即安装的版本与“必需”版本不同,则可能会出现问题。
其他区别是 npm ci
从不接触您的 package*.json
文件。如果 package.json
和 package-lock.json
文件中的依赖项版本不匹配,它将停止安装并显示错误。
您可以从官方文档 here 中阅读更好的解释。
此外,您可能还想了解包锁here。
值得记住的是,像 alpine 这样的轻节点 docker 映像没有安装 Python,它是 npm ci
使用的 node-gyp
的依赖项。
我认为为了让 npm ci
正常工作,您需要在构建中安装 Python 作为依赖项,这有点固执己见。
更多信息在这里Docker and npm - gyp ERR! not ok
react-scripts
的问题,而不是由于 npm ci
从我发现在 npm ci
中没有对 python
的依赖
它会进行全新安装,在删除 node_modules 并重新运行 npm i
的情况下使用它。
我不知道为什么有些人认为它是“持续集成”的缩写。有一个可以作为 npm i
运行的 npm install
命令和一个可以作为 npm ci
运行的 npm clean-install
命令。
npm install
可以写入 package.json。你知道它可以在这里写什么吗?npm install package
可以同时修改package-lock.json
和package.json
,而没有参数的npm install
只能修改package-lock.json
npm i
和npm ci
,devDependencies
的 @Link14 安装由--production
标志或NODE_ENV
环境变量控制npm ci
中的ci
更好地理解为全新安装而不是持续集成。