Skip to content

What kind of npm dependency is this?

Christopher Willis-Ford edited this page Jul 6, 2021 · 1 revision

In general, a dependency should be listed in dependencies if its primary role is to contribute its code as part as part of the runtime of the module in question. Otherwise, for example if it is involved in testing, building, or releasing the module, it should be listed in devDependencies.

In some cases, especially for a module using a compiler or transpiler, this can be a fairly subtle distinction. Here are a few examples:

Dep Type Why?
import('foo') or require('foo') under src/ dependencies This code will be directly included in the module at runtime.
tap, jest, etc. devDependencies Test utilities are generally consumers of the module; they're only dependencies in the sense that they're required for some portion of the development process.
import('foo') or require('foo') in tests devDependencies Like tap and friends, these are only required for some portion of the development process and do not contribute to the module at runtime.
webpack devDependencies While webpack does contribute some code to the runtime (for example, module management or node/browser polyfills) that isn't its primary role.
require('foo-loader?...') under src/ devDependencies A loader's main role is to process data (from src/ or similar) which will be included in the module at runtime. In general the loader contributes even less of its own code than webpack.
Used by "runtime" npm script like install dependencies This script family will be called when a consumer of your module installs its dependencies, even with --only=prod, so the dependency will be needed even in non-dev situations.
Used by "production" npm script like prepublish, prepare, or shrinkwrap dependencies These script families run when your module is the "root" of the npm install / npm ci process, even with --only=prod, so the dependency will be needed even in non-dev situations.
Used by other npm scripts devDependencies Other scripts will only be used by developer-style npm lifetime events or by developers or build scripts.
npx foo in CI or package.json scripts devDependencies or unlisted The npx tool will automatically download and install the necessary module in a temporary location, so there's no need to list it in package.json at all. If you need a specific version of the package, it might make sense to list it in devDependencies -- but only if it's needed for regular development. Modules used only on CI for release/deploy should not be listed, for example.

If a dependency falls in both categories -- for example, if it's referenced by code in src/ and also in tests -- then it should be listed in dependencies.

To see when various npm scripts run, check out npm-scripts-demo.

What about peer dependencies?

The peerDependencies list is a way to express that your module works with a specific version (or version range) of another module, but neither directly depends on the other. In other words, it's information for the consumer of your module.

More information about peer dependencies is available here: https://nodejs.org/es/blog/npm/peer-dependencies/