Choose dependencies or devDependencies in Node.js
Classify packages by how your project is built and deployed, and understand production installs, peer dependencies, and optional packages.
Put packages required by the deployed application in dependencies. Put tools used only to develop, test, or build it in devDependencies. The distinction depends on the artifact you deploy: a compiler can be a development dependency even when its output runs in production.
Classify a package by its role
npm install express
npm install --save-dev typescript eslint
For a new package entry, the first command normally saves a production dependency; the second explicitly saves development dependencies. A typical manifest looks like this:
{
"dependencies": { "express": "^5.0.0" },
"devDependencies": { "typescript": "^5.0.0", "eslint": "^9.0.0" }
}
The versions illustrate the categories; choose versions compatible with your actual project. A test runner, formatter, or bundler usually belongs in devDependencies. A server library loaded at runtime belongs in dependencies. A polyfill or client library may be bundled into an output artifact, so inspect the build and deployment path instead of classifying by package name alone.
Install for development or deployment
npm ci
# In a separate deployment installation, when build tools are no longer needed:
npm ci --omit=dev
A production-only installation cannot run a build that requires omitted tools. Build in an earlier stage, then deploy the output with its runtime dependencies. NODE_ENV=production changes npm's default omit behavior, but explicit include/omit settings can override it. NODE_ENV also affects application behavior separately from installation.
Omitted development packages can still appear in package-lock.json; omission controls the on-disk installation, not whether npm records the dependency graph. When another project installs your published package, it does not install your package's development dependencies as part of that consumer's normal dependency tree.
Peer, optional, and bundled dependencies
| Field | Purpose |
|---|---|
peerDependencies |
Declare compatibility with a host package, such as a plugin's framework |
optionalDependencies |
Permit an installation to proceed when that dependency cannot be installed; code must handle its absence |
bundledDependencies |
Identify packages included when the package is packed for distribution |
npm 7 and later normally install peers automatically. Conflicts can produce warnings or errors depending on the graph and settings; strict peer handling is configurable. A peer marked optional through peerDependenciesMeta is not automatically installed in the same way.
A library may list a framework as both a peer dependency and a development dependency: the peer documents consumer compatibility, while the development dependency supports local tests. Replacing a peer with an ordinary dependency changes the relationship and can introduce an unwanted separate copy.
Verify before shipping
A package listed in the wrong section may work locally and fail after a production install. Test the actual built artifact with the same install policy used in deployment. Commit the manifest and lockfile together, and review dependency changes rather than treating every compatible version range as a guarantee of compatibility.
See npm package.json fields and npm ci.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan