Modules and npm

npm dependencies and devDependencies

Learn the difference between npm dependencies and devDependencies, how the -D flag adds dev-only packages, and how --production skips them on deploy.

When you install an npm package with npm install <package-name>, npm records it as a dependency by default:

npm install fastify

Use -D, short for --save-dev, for a development dependency:

npm install -D eslint

The distinction is about when the running application needs the package:

  • dependencies are required when production code runs
  • devDependencies are needed only to develop, test, lint, or build the project

A package imported by the running server belongs in dependencies. A test runner normally belongs in devDependencies. Build tools require judgment: if the deployment builds from source, the build stage needs them. A runtime image with already-built output may not.

Both sections contain version ranges. The exact resolved tree belongs in package-lock.json, including development packages even when they are omitted from one install.

For a production-only install, current npm uses:

npm ci --omit=dev

The older --production option is still recognized, but --omit=dev states the intent directly. Omitted development packages remain represented in the lockfile. They are just not physically installed in that node_modules tree.

Do not classify a dependency by package reputation. A compiler can be runtime-critical in one architecture and development-only in another. Start from the exact production command and ask whether it imports or executes the package.

Test the production artifact in a clean environment. A local machine can hide a mistake because a dev dependency or globally installed tool happens to be available.

Try this on your own project: classify your direct packages from its real start and build commands. Run a clean npm ci --omit=dev, start the production artifact, and move any missing runtime package to the correct section.

Lesson completed