How to Use NPM --legacy-peer-deps command
Need to understand what the purpose of the flag --legacy-peer-deps for NPM? This post will tell you how to use it and best practice!
Jan 23, 2023 | Read time 8 minutes🔔 Table of contents
Introduction
A common misunderstanding when updating NPM packages is dealing with the –legacy-peer-deps flag for NPM.
You can use the –legacy-peer-deps flag by doing the following NPM command.
npm install --legacy-peer-deps
Sometimes you will see errors like the below output:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: nexttwin@0.1.0
npm ERR! Found: react@17.0.1
npm ERR! node_modules/react
npm ERR! react@"17.0.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^16.8.0" from react-hook-mousetrap@2.0.4
npm ERR! node_modules/react-hook-mousetrap
npm ERR! react-hook-mousetrap@"*" from the root project
npm ERR!
Another error that can come up is:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: my-first-app@0.0.0
npm ERR! Found: @angular/compiler@11.0.9
npm ERR! node_modules/@angular/compiler
npm ERR! @angular/compiler@"~11.0.0" from the root project
npm ERR! peer @angular/compiler@"11.0.9" from @angular/compiler-cli@11.0.9
npm ERR! node_modules/@angular/compiler-cli
npm ERR! dev @angular/compiler-cli@"~11.0.0" from the root project
npm ERR! peer @angular/compiler-cli@"^11.0.0" from @angular-devkit/build-angular@0.1100.7
npm ERR! node_modules/@angular-devkit/build-angular
npm ERR! dev @angular-devkit/build-angular@"~0.1100.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @angular/compiler@"11.1.2" from @angular/localize@11.1.2
npm ERR! node_modules/@angular/localize
npm ERR! peerOptional @angular/localize@"^11.0.0" from @angular-devkit/build-angular@0.1100.7
npm ERR! node_modules/@angular-devkit/build-angular
npm ERR! dev @angular-devkit/build-angular@"~0.1100.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /Users/amit/.npm/eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/amit/.npm/_logs/2021-02-04T17_58_24_981Z-debug.log
What does the --legacy-peer-deps
flag do?
This flag tells NPM to completely ignore peerDependencies when building a package tree. This is the default functionality in NPM versions 3 through 6.
With NPM versions 7+, it installs peerDependencies by default (also installs the packages that “peer-depend” on them).
Now one way of thinking about the --legacy-peer-deps
is that it is telling NPM to ignore installing peer dependencies.
What is a peer dependency anyway?
NPM peer dependencies are a way for a package to specify other packages that are required for it to function properly.
These dependencies are considered “peer” dependencies because they are not dependent on the package itself, but rather are required by the package to work in conjunction with other packages. An example of this is the react-datepicker
package. The package contains peer dependencies for:
- react
- react-dom
If we look at the package.json for react-datepicker we can see:
{
"author": "HackerOne",
"name": "react-datepicker",
"description": "A simple and reusable datepicker component for React",
"version": "4.8.0",
"license": "MIT",
...
"peerDependencies": {
"react": "^16.9.0 || ^17 || ^18",
"react-dom": "^16.9.0 || ^17 || ^18"
},
}
So when someone decides to do the command install react-datepicker npm install react-datepicker
, the need to have react versions “^16.9.0 || ^17 || ^18” and react-dom versions “^16.9.0 || ^17 || ^18” already in their projects.
When a package has peer dependencies, the package’s users are responsible for installing those dependencies themselves. This is different from regular dependencies, which are automatically installed when the package is installed.
In package.json file, peer dependencies is represented as the “peerDependencies” object key!
For example, if package A has a peer dependency on package B, the package.json file for package A might look like this:
{
"name": "package-a",
"version": "1.0.0",
"peerDependencies": {
"package-b": "^2.0.0"
}
}
The --legacy-peer-deps
flag and React
The inclusion of this flag for NPM 7+ is partly due to React v17+. We encounter the associated error of unable to resolve dependency tree
when running npm installs within a v17 React application.
A lot of React modules have not updated their peerDependencies to have React 17+ and thus causing the unable to resolve dependency tree
.
As an example, a developer might start a new project with React version 17. Now when they start installing third-party packages that still have peerDependency of React 16 this will cause problems.
We have three options in this case:
- Use the
--legacy-peer-deps
flag and ignore the error - Wait for the author of the third-party package to update their peer dependency to React 17
- Start the project with React 16 or install both React 17 and 16 in the same project (not recommended)
How to check for peerDependencies
NPM itself doesn’t list peer deps on the pages of a given module. However, there is a simple workaround to check for peer deps, either before or after install. Simply run:
npm info name-of-module peerDependencies
This command will return the name of each peerDependency along with all compatible version(s).
Should I use the --force
flag or --legacy-peer-deps
flag?
There are sometimes confusion on what to use when we see the dreaded unable to resolve dependency tree
error - use the --force
flag or --legacy-peer-deps
flag?
Generally, we want to use the --force
flag since this tells NPM to try to set a different peer dependency when it sees conflicting dependencies.
As for the --legacy-peer-deps
flat, it tells NPM to ignore peer dependencies completely. This can stuff up your dependency resolution in the long run.
Although, using force is still not that great, since it will take up more disk space in your node_modules folder - eg fetching different versions and storing them locally!
Adding a per project .npmrc file --legacy-peer-deps
If you want to set the --legacy-peer-deps
flag by default for all of your NPM installs, then you can consider updating the .npmrc file.
The .npmrc file is a configuration file used by the Node Package Manager (npm) to manage settings and options for the npm client.
It can be located in four locations:
- the user’s home directory,
- the project root directory,
- NPM install directory
- Global directory
It’s also possible to set environment variables to configure npm. But, the .npmrc file provides a way to configure npm options for a specific user or project, without modifying the environment variables on the system.
So for example, lets say we have a typical folder structure like the following:
my-app/
├─ node_modules/
├─ public/
│ ├─ favicon.ico
│ ├─ index.html
│ ├─ robots.txt
├─ src/
│ ├─ index.css
│ ├─ index.js
├─ .gitignore
├─ .npmrc
├─ package.json
├─ README.md
We can have the legacy-peer-deps
flag in .npmrc file.
# .npmrc
legacy-peer-deps=true
Summary
In this post I went over how to use the --legacy-peer-deps
flag for NPM.
As of NPM version 7+, they require to install peerDependencies by default. So we need to use this --legacy-peer-deps
flag to tell NPM to keep the behaviour of NPM version 6 or below where peerDependencies are ignored.