Programming
Coding Commands
Web Development
Node.js
npm

What is the difference between --save and --save-dev?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In npm, the real distinction is not between two command flags so much as between two dependency categories: dependencies and devDependencies. Historically --save and --save-dev controlled where a package was written in package.json, but modern npm behavior makes one of those flags largely historical.

What --save Originally Meant

Older npm versions did not automatically write installed packages into package.json. That is why --save existed.

bash
npm install react --save

This meant “install react and record it under dependencies.” Packages in dependencies are required for the application to run in normal usage.

In modern npm, a plain install already saves to dependencies by default, so --save is usually unnecessary.

bash
npm install react

That is why many developers now treat --save as legacy or redundant syntax.

What --save-dev Means

--save-dev records the package under devDependencies.

bash
npm install jest --save-dev

This is for packages needed during development, testing, linting, compiling, or building, but not for the runtime behavior of the application itself.

Typical examples include:

  • test frameworks such as Jest
  • bundlers such as Webpack
  • transpilers such as Babel
  • linting tools such as ESLint

The Real Concept: Runtime Versus Development

The right decision is based on when the package is needed.

  • If the app needs it to start or run, put it in dependencies.
  • If only developers or build pipelines need it, put it in devDependencies.

For example, React belongs in dependencies because the app needs it to run. Jest belongs in devDependencies because production users do not need the test runner.

Why This Matters

Dependency categories affect install behavior, deployment size, and mental clarity. A cleaner package.json helps people understand which packages are part of the runtime contract and which are only development tooling.

It also helps deployment environments avoid carrying unnecessary packages when only runtime dependencies are needed.

Modern Practical Rule

For current npm usage, think in terms of these commands:

bash
npm install <package>
npm install <package> --save-dev

The first is for runtime dependencies. The second is for development-only tooling.

That rule is easier to remember than thinking about --save as an actively meaningful choice in modern npm.

If you are reviewing an existing project, the quickest way to understand its dependency model is to inspect whether packages are needed by the running application or only by local development and build scripts. The command flags are just how that decision gets recorded.

Once you focus on that distinction, the npm syntax becomes much less confusing.

That is the part worth remembering.

The rest is mostly historical syntax.

That framing usually keeps teams out of trouble.

Common Pitfalls

  • Installing build tools into dependencies even though production runtime does not need them.
  • Treating --save as if it still changes modern npm behavior in a meaningful way for most setups.
  • Putting runtime libraries in devDependencies and then breaking production installs.
  • Thinking the question is about command syntax only instead of dependency semantics.
  • Letting package.json drift until nobody can tell which packages are needed to run the app.

Summary

  • '--save historically wrote packages to dependencies, but modern npm usually does that by default.'
  • '--save-dev writes packages to devDependencies.'
  • The real distinction is runtime dependency versus development-only tooling.
  • Use dependencies for what the app needs to run.
  • Use devDependencies for tests, build tools, and local development support.

Course illustration
Course illustration

All Rights Reserved.