ChatGPT解决这个技术问题 Extra ChatGPT

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

我正在使用持续集成并发现了 npm ci 命令。

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

它更快吗?它是否使测试更难,好吗?


D
David Lambl

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 cipackage-lock.jsonnpm-shrinkwrap.json 生成整个依赖关系树时,npm install 使用以下算法 (source) 更新 node_modules 的内容:

从磁盘加载现有的 node_modules 树具有克隆树的原始树并列出将一个转换为另一个要执行的所有操作,最深的第一类操作是安装、更新、删除和移动


我不知道 npm install 可以写入 package.json。你知道它可以在这里写什么吗?
好吧,这可能有点误导......当您使用它来安装、更新或删除依赖项时,它会写入 package.json。我会在文中说得更清楚,谢谢!
npm install package 可以同时修改 package-lock.json package.json,而没有参数的 npm install 只能修改 package-lock.json
对于 npm inpm cidevDependencies 的 @Link14 安装由 --production 标志或 NODE_ENV 环境变量控制
虽然文档中没有明确说明,但 npm ci 中的 ci 更好地理解为全新安装而不是持续集成。
p
phoenix

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


删除预先存在的 node_modules 可能会使构建速度变慢
也许不提交 node_modules?
@jontro,我的同事测量了 docker 中的命令,发现对于我们的包 ci 比 install 快得多(40 秒对 130 秒),但是 YMMV。
@MichaelFreidgeim 是预先存在的 node_modules 还是从头开始?
@jontro,据我了解 dockerfile 命令' WORKDIR /src COPY src/package.json 。复制 src/package-lock.json 。运行 npm ci --no-optional; ' 每次都重新创建 node_modules。
b
basickarl

虽然其他人都回答了技术差异,但没有人解释在什么情况下使用两者。

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

当您想要缓存 node_modules 目录时,npm install 非常适合开发和 CI。什么时候用这个?如果您正在制作一个包供其他人使用,则可以这样做(您在这样的版本中不包括 node_modules。关于缓存,请注意,如果您计划支持不同版本的 Node.js,请记住,由于 Node.js 运行时要求之间的差异,可能必须重新安装 node_modules。如果您想坚持使用一个版本,请坚持使用最新的 LTS

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

npm inpm ci 都使用 npm 缓存(如果存在),此缓存通常位于 ~/.npm

此外,npm ci 尊重 package-lock.json 文件。与 npm install 不同,它重写文件并始终安装新版本。

奖励:您可以根据自己的复杂程度混合它们。在 git 中的功能分支上,您可以缓存 node_modules 以提高团队的工作效率,而在合并请求和主分支上,则依赖 npm ci 来获得确定性结果。


我认为在任何情况下都不应使用 npm i 而不是 npm ci,除非您要更新依赖项。 npm ci 总是更好,因为确定性行为总是更好
@enanone 正如我所说的,npm i 缓存速度更快,而 npm ci 速度较慢,因为它会进行完全重新安装。它们都很有用。
如果每个包都在 npm 缓存中,npm ci 也一样快
在我的例子中,npm ci 即使在使用本地 NPM 缓存重复执行时也会明显变慢:npm install 大约为 2 秒,npm ci 为同一项目运行时为 16 秒。清除缓存后,它们是相同的。我们迫切需要可以从 package-lock 安装但不要从删除 node_modules 开始的东西:github.com/npm/cli/issues/564
@Piedone 我想说删除 node_modules 是一项功能,因为我已经看到开发人员在其中进行了一些自定义更改,并且想知道为什么它不适用于生产。我总是更喜欢一个具有重复完全相同结果的命令,而不是看似更快的命令。然而,npm install 可能会改变 package-lock.json 的事实对于依赖管理器来说是一个非常糟糕的默认设置,并且对于 npm ci 来说也是一个巨大的胜利。即使在我的开发机器上,我也总是使用 ci 进行纯安装,并且仅当我想更新或添加新的依赖项时才使用 install
O
OscarRyz

您链接的文档有摘要:

简而言之,使用 npm install 和 npm ci 的主要区别是: 项目必须有一个现有的 package-lock.json 或 npm-shrinkwrap.json。如果包锁中的依赖项与 package.json 中的依赖项不匹配,npm ci 将退出并报错,而不是更新包锁。 npm ci 一次只能安装整个项目:无法使用此命令添加单个依赖项。如果 node_modules 已经存在,它将在 npm ci 开始安装之前自动删除。它永远不会写入 package.json 或任何包锁:安装基本上是冻结的。


k
krishnakeshan

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

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

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

您可以从官方文档 here 中阅读更好的解释。

此外,您可能还想了解包锁here


t
teseo

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

我认为为了让 npm ci 正常工作,您需要在构建中安装 Python 作为依赖项,这有点固执己见。

更多信息在这里Docker and npm - gyp ERR! not ok


根据您发布的问题,他们遇到了 react-scripts 的问题,而不是由于 npm ci 从我发现在 npm ci 中没有对 python 的依赖
S
Scott Bishop

它会进行全新安装,在删除 node_modules 并重新运行 npm i 的情况下使用它。

我不知道为什么有些人认为它是“持续集成”的缩写。有一个可以作为 npm i 运行的 npm install 命令和一个可以作为 npm ci 运行的 npm clean-install 命令。