An In-Depth Explanation of package.json’s Dependencies
By: Jennifer Fu
Tags: Package, Rollup, Peer Dependencies, Webpack, External Dependencies

Types of Dependencies

There are five types of dependencies defined in the npm documentation:

1. Normal dependencies

The normal dependencies: These dependent packages serve as libraries to make a project work.

The final product must be bundled with these packages, which might be frameworks (such as React, Angular, Vue, etc.), utilities (such as i18next, Lodash, axios, etc.), and subcomponents in your organization.

"dependencies": {

"axio": "0.19.0",

"i18next": "~17.0.6",

"react": "^16.12.0",

"react-dom": "^16.12.0",

"react-i18next": "~10.11.4",

"react-router-dom": "~5.1.2"

}

2. devDependencies

These dependent packages serve as tools for development. The final product doesn’t need these packages, which might be:

Formatting tools (Prettier, Beautifier, ESLint, etc.).

Transpilers (Babel, TypeScript, etc.).

Type definitions ( @types/react , @types/jest , etc).

, , etc). Bundlers (webpack, gulp, rollup, etc.).

Test libraries (Jest, TestCafe, Enzyme, Testing Library, etc.).

Document libraries (JSDoc, Document, etc.).

Monorepos tools (lerna, Bit, etc.).

And many other types of libraries.

"devDependencies": {

"@types/jest": "24.0.18",

"@types/react": "16.8.23",

"@typescript-eslint/eslint-plugin": "2.8.0",

"@typescript-eslint/parser": "2.8.0",

"eslint": "^5.16.0",

"husky": "^3.0.0",

"lerna": "^3.16.4",

"prettier": "^1.18.2",

"rollup": "^1.0.0",

"typescript": "^3.6.4"

}

3. peerDependencies

These dependent packages are needed by a product, similar to the normal dependencies. However, this product is not a final product. Instead, it is a library or plugin to be consumed by a host application.

For this situation, it is recommended to put the dependencies in the peerDependencies and expect the host application to include it.

There are a few reasons for this approach:

It would keep the intermediate product’s package size small without external packages. It would not unnecessarily bundle the intermediate product with the fixed version third-party dependencies. The consuming host application itself may require the same packages. The consuming host application may depend on a number of libraries or plugins requiring the same packages, with the same versions or compatible versions.

"peerDependencies": {

"jest": ">=24 <25"

} # This way, npm will issue a warning when some peer dependencies are missing. npm WARN ts-jest@24.2.0 requires a peer of jest@>=24 <25 but none is installed. You must install peer dependencies yourself.

From version 4, npm dropped support for installing peerDependencies automatically, due to the technical challenges of deduplication algorithm.

But from version 7, npm uses the Arborist algorithm to automatically install peerDependencies .

peerDependenciesMeta provides additional information on how peerDependencies are to be used. Specifically, it allows peerDependencies to be marked as optional.

"peerDependencies": {

"jest": ">=24 <25"

}

"peerDependenciesMeta": {

"jest": {

"optional": true

}

}

When a user installs packages, npm will emit warnings if packages specified in peerDependencies are not already installed. Marking a peer dependency as optional ensures npm will not emit a warning if the jest package is not installed on the host.

4. optionalDependencies

These dependent packages are needed by a product, similar to the normal dependencies.

However, npm will proceed if it cannot find them or fails to install. The product should have the capability to handle these type of issues. This is a rarely-used type.

5. bundledDependencies

These dependent packages are bundled when publishing the package. This preserves npm packages locally or has them available through a single file download.