"--save"和"--save-dev"有什么区别?

1225

什么是以下两者的区别:

npm install [package_name]

并且:

npm install [package_name] --save

而且:

npm install [package_name] --save-dev

这是什么意思?--save-dev 关键字的真正效果是什么?


5
如果您使用像Jenkins这样的持续集成工具,它是否知道在运行测试时使用devDependencies模块?我认为是的,但这并不是非常明显的。 - Alexander Mills
10
请问您需要的翻译是:“也许编辑问题,同时说明dependencies和devDependencies之间的功能区别是什么?” - Alexander Mills
12
当用户执行 npm install --production 命令时,通过 --save-dev 选项安装的包将不会被重新安装。这是操作上的区别(有关更多信息,请参见 https://docs.npmjs.com/cli/install)。 - Andrew
5
如果您将环境变量 NODE_ENV 设置为生产模式,那么只需运行 npm install 命令,开发依赖包将自动被排除。 - Muhammad Umer
真正的问题是这只是一个不清晰的区分,可以在节点/npm方面得到改进。在开发时,--save和--save-dev之间没有明显的区别。以 moment.js 示例为例:在运行 webpack 时,moment 代码从 node_modules 中取出并包含在项目中。在这个意义上,这与运行 webpack 时所需的 typescript 没有区别。 - Kokodoko
18个回答

976
< p > 在自己的项目中尝试了 < code > --save 和 < code > --save-dev 后,可能不会立即注意到它们之间的区别。因此这里有一些例子...

假设你正在构建一个应用程序,该应用程序使用moment包来解析和显示日期。你的应用程序是一个调度程序,所以它确实需要这个包来运行,就像没有它无法运行。在这种情况下,你应该使用

npm install moment --save

这将在你的 package.json 中创建一个新值。

"dependencies": {
   ...
   "moment": "^2.17.1"
}

在开发过程中,使用测试套件等工具真的很有帮助,可能需要使用 jasmine-corekarma。在这种情况下,您将使用:

npm install jasmine-core --save-dev
npm install karma --save-dev

这也会在您的package.json中创建一个新值。

"devDependencies": {
    ...
    "jasmine-core": "^2.5.2",
    "karma": "^1.4.1",
}

即使在文档中,它也要求您对诸如测试套件之类的模块使用 --save-dev

依赖项

依赖项在一个简单的对象中指定,该对象将包名称映射到版本范围。版本范围是一个带有一个或多个空格分隔符的字符串。依赖关系还可以用tarball或git URL标识。

请勿在您的依赖项对象中放置测试harnesses或转换器。参见下面的devDependencies。

您不需要测试套件以正常状态运行应用程序,因此它是一种--save-dev类型的依赖关系,仅此而已。如果您不理解实际发生的情况,很难想象。

取自NPM文档docs#dependencies


63
我认为,“save”关键字存在问题。 为什么不为开发和部署分别设置“-dev”和“-deploy”标志呢?这比使用“save”关键字更有意义。 - Thinh Vu
2
为什么包不能自己知道(决定)它是一个发布包还是一个开发包,并且--save可以用于两者。当包开发人员创建意图时,让安装用户决定这一点似乎很奇怪。 - CodeGrue
9
如果你只是用jQuery来测试React组件,那么它应该被放在save-dev中,但你可能实际上并不会用它来构建你的主项目。是的,这是可能的。那么为什么打包工具需要知道你对它的使用方式呢? - Michael Bruce
4
非常清晰。我是一个嵌入式开发人员,第一次学习Bootstra + Node.js工作流程。一时半会并不明显它们之间的区别。 - Leroy105
4
@YakovL 中的 save-dev 表示当其他人将您的软件包作为其依赖项安装时,这些软件包不会被安装。仅用于运行脚本(如 start/build)的软件包在该情况下也不需要,因此它们被放置在 dev-dependencies 中。如果您正在开发一个 Web 应用程序而不是供他人使用的软件包,则可能根本不必担心它。 - riv
显示剩余6条评论

823
  • --save-dev 用于保存用于开发目的的软件包。 例如:单元测试,代码压缩等。
  • --save 用于保存应用程序运行所需的软件包。

193
它们有什么不同?我何时应该使用其中之一?如果它在--save-dev下,我仍然可以在生产中使用它吗? - Dave Voyles
26
答案简明地回答了你的前两个问题。最后一个问题的答案是:“如果它被标记为--save-dev,我还能在生产环境中使用这个包吗?”答案是“不行”。虽然这样做肯定是“可能”的,但这并不是预期的用法。 - Technetium
84
"-D" 是 "--save-dev" 的缩写,"-S" 是 "--save" 的缩写。 - chrisco
249
这个答案含糊不清,举一个小例子会有很大帮助让它更加清晰明了。 - Choylton B. Higginbottom
55
请注意,从npm 5.0.0版本开始,“--save”选项已不再需要。如果你运行命令“npm install my-package”,它会在package.json文件中将“my-package”添加为依赖项。 - Martin Carel
显示剩余6条评论

236

默认情况下,NPM会将一个软件包安装在node_modules目录下。当您尝试为应用程序/模块安装依赖项时,需要先安装它们,然后将它们添加到package.json文件的dependencies部分中。

--save-dev将第三方软件包添加到软件包的开发依赖项中。当有人直接运行npm install来安装您的软件包时,它不会被安装。通常只有当有人首先克隆您的源代码仓库,然后在其中运行npm install时才安装它。

--save将第三方软件包添加到软件包的依赖项中。每当有人运行npm install package时,它将与软件包一起安装。

Dev依赖项是仅用于开发软件包的依赖项。这可能包括测试运行器、编译器、打包工具等。 这两种类型的依赖项都存储在软件包的package.json文件中。--save添加到dependencies--save-dev添加到devDependencies

有关更多信息,请参阅npm install文档。

--

请注意,自NPM 5以来,--save现在是默认选项。因此,不再需要显式使用它。可以通过在不使用--save的情况下运行npm install来实现相同的结果。


63
如果您正在构建一个不会从 npm 下载的 Web 应用程序,可以使用 --save-dev 和 --save 互换使用,但如果您正在开发一个要与他人共享的软件包,则了解这两者的区别非常重要。请注意,该语句的含义为:在构建 Web 应用程序时,--save-dev 和 --save 可以互换使用;但是,在开发要与他人共享的软件包时,了解它们之间的区别非常重要。 - VFein
27
谢谢你,终于有人说出了使用npm install的目的。 - user5228393
10
从2017年npm 5版本开始,使用npm install命令将默认添加--save参数。这个改变不会改变原有的意思,只是让表达更加通俗易懂。 - nCardot
等等,为什么要用复杂的句子?在 DevDependency 中,开发人员可以安装软件包,并且只会更新 devDependency。因此,当新的开发人员克隆项目代码库并运行 npm install => 只有“依赖软件包名称”将被安装在 node_modules 中...而不是像 Dev-dependency 中那样安装开发人员的软件包。 - Anupam Maurya
1
这怎么不是最佳答案呢?任何有阅读能力的人都可以看出 --save-dev 是用于开发环境的;其他答案都是无用的。这个答案指明了 --save--save-dev 实际上行为不同 - Aaron Beaudoin

153

让我举个例子,

  • 你是一个非常严肃的npm库的开发者,该库使用不同的测试库来测试包。
  • 用户下载你的库并想在他们的代码中使用它。他们需要下载你的测试库吗?也许你使用jest进行测试,而他们使用mocha。你想让他们也安装jest吗?只为了运行你的库吗?

不需要。对吧?这就是为什么它们放在devDependencies中。

当有人执行npm i yourPackage时,只会安装运行你的库所需的库。其他用于打包你的代码、测试和模拟的库不会被安装,因为你将它们放在devDependencies中。相当不错,对吧?

那么,为什么开发者需要暴露devDependancies呢?

假设你的包是一个开源包,有上百个人向你的包发送pull request。那么他们如何测试包呢?他们会git clone你的存储库,当他们执行npm i时,会安装dependencies以及devDependencies

因为他们没有使用你的软件包。他们正在进一步开发这个软件包,因此为了测试你的软件包,他们需要通过现有的测试用例以及编写新的测试用例。所以,他们需要使用你的devDependencies,其中包含了你使用的所有测试/构建/模拟库。

82

这的确是一个完美的例子:

$ npm install typescript --save-dev
在这种情况下,您需要在开发过程中使用Typescript(一种可解析Javascript的编程语言),但一旦应用程序部署,它就不再需要,因为所有代码都已被转译为Javascript。因此,在发布的应用程序中包含它是没有意义的。实际上,这只会占用空间并增加下载时间。

4
同样适用于"$ npm install grunt --save-dev",它对开发很有用,但不适用于部署。 - Jack
1
一则注记:微软建议将@types/xxx包安装为依赖项,而不是devDependencies。https://github.com/Microsoft/types-publisher/issues/81 - Dave
2
我觉得令人困惑的是这有什么关系呢?使用“--save”保存的包仍然只保存在“node_modules”文件夹中。代码不会被包含在部署的网站中。 - Kokodoko
7
当你使用 --save-dev 标记时,该包会被添加到你的 devDependencies 对象中。如果/当有人安装你的包时,所有的 dependencies 都会被下载,但 devDependencies 不会被下载,因为它们在运行时不是必需的。正如答案所述,这可以节省他们的时间和空间。在处理你的包文件时,开发者只需要在包目录内运行 npm install 即可安装 devDependencies - Jasjit Singh Marwah
@Kokodoko 反过来说:只有当你从 Github 下载一个仓库并键入 npm install 时,才会安装 devDependencies - PoolloverNathan
显示剩余2条评论

36

根据此答案中@andreas-hultgren的建议以及npm文档

如果有人计划在他们的程序中下载和使用您的模块,则他们可能不需要下载和构建您使用的外部测试或文档框架。

但是,对于Web应用程序开发,Yeoman(一个安装经过同行评审的预先编写的package.json文件等工具的脚手架工具)将所有软件包放在devDependencies中,并且没有放置在dependencies中,因此在Web应用程序开发中使用--save-dev功能似乎是一个安全的选择。


3
请注意,当我使用gulp并使用“--save-dev”安装软件包时,我遇到了问题,其中该软件包无法安装其所需的依赖项。运行“--save”可安装这些缺失的依赖项。 - Nick M
20
我想指出的是,根据 npm 文档,除了测试和文档依赖项外,我现在使用 --save 命令来安装所有其他依赖项。我开始认为我之前提到的 Yeoman 示例 并不是 最佳实践的好例子。 - wayfarer_boy
我也这么认为,为什么你需要 --save-dev 在这里的每个答案中都越来越不清楚了 :) - Kokodoko

26

--save-dev 将 semver 规范保存在包描述文件的 "devDependencies" 数组中,--save 则保存在 "dependencies" 中。


93
什么是功能上的区别? - ahnbizcad
9
这个答案对我来说最有意义,devDependencies仅在开发过程中需要,而不是生产环境,因此需要htmllint、sass编译等。而Dependencies则是用于生产需求,例如Diaporama需要存在才能运行。 - miller the gorilla
3
@ahnbizcad 这里有更好的答案(https://dev59.com/VmMk5IYBdhLWcg3w5B3y),但主要的功能区别在于devDependencies不会被传递包含。 - Pace
对于那些不了解的人来说,最直观的描述方式难道不是这样吗?:Dev --save-dev 使包局部安装到您的项目中,而 --save 则将它们安装到您的 node 安装中? - ahnbizcad

21

--save-dev 用于开发应用时使用的模块,但在生产环境中运行它不需要。

--save 用于将模块添加到 package.json 中,并且在应用程序运行时需要这些模块。

例如:express、body-parser、lodash、helmet、mysql 这些模块是在运行应用程序时使用的,使用 --save 将它们放到依赖项中。而 mocha、istanbul、chai、sonarqube-scanner 等模块是在开发过程中使用的,因此将它们放到 dev-dependencies 中。

npm link 或 npm install 命令也会在项目文件夹中安装依赖项和开发依赖项模块。


17
完整性阅读并遗忘--save-dev的头疼

最简单的答案是,在创建面向其他开发人员软件包并希望将其托管在类似NPM Registry(如lodash、mongoose、express等)的仓库时,--save-dev非常有用。当您正在构建或编写一个Node服务器时,--save--save-dev之间没有区别,因为您的Node服务器实现对您私有且永远不会发布到NPM上。

NPM安装的工作原理

每当我们使用 npm 安装新包,例如 npm install express,那么 NPM 就会将该包安装到我们的系统中并将其放入 node_modules 文件夹中。现在,NPM 将分析新安装包(例如这种情况下的 express)的 package.json 文件,分析后将安装那些在 express 包的 package.json 文件的 dependencies 部分中提到的所有包。在安装了 express 依赖的这些包之后,NPM 再次分析所有新安装包的 package.json 文件,再次为它们安装包,这个过程会一直持续,直到所有依赖包都可用于正确运行。您可以通过在指向项目目录位置的终端中运行 npm list 来检查软件包依赖项。
—save-dev 与上述内容有什么关系?假设您想像express一样创建一个新的,在开发这个新的包时,您可能想编写一些单元测试代码,并使用任何其他可用的测试包(假设为mocha)测试该包。现在,您知道mocha仅需要用于测试包,而不需要用于使用包。在这种情况下,您应该使用--save-dev标志安装mocha,否则NPM会在开发人员使用NPM安装您的包时安装它。因此,如果我们希望某个依赖项在有人从NPM安装我们的包时未被安装,我们必须在开发阶段使用--save-dev安装该包。 最后一件事 不要将--save-dev协作开发混淆,如果有人从源代码版本控制系统(如github)克隆了您的包代码,那么NPM肯定也会安装所有devDependencies,即使用--save-dev安装的包。

15
当您使用 npm install <package-name> 安装 npm 包时,您正在安装其作为依赖项。
该包会自动列在 package.json 文件中的 dependencies 列表下(从 npm 5 开始:以前需要手动指定 --save)。 例如:npm install lodash 按回车键后,请检查 package.json 文件。
"dependencies": {
    "lodash": "4.x",  
},
当您添加-D标志或--save-dev时,您正在将其安装为开发依赖项,这将它添加到devDependencies列表中。 例如:npm install --save-dev lite-server 输入后,请检查您的package.json文件。
"devDependencies": {
    "lite-server": "^2.6.1"
},

开发依赖项是指仅用于开发的软件包,不需要在生产中使用。例如测试软件包,webpack或Babel。

当您进入生产环境时,如果键入npm install并且文件夹包含package.json文件,则它们将被安装,因为npm假定这是一个开发部署。

您需要设置--production标志(npm install --production)以避免安装这些开发依赖项。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接