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.

👋 About the Author

G'day! I am Huy a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube