pnpm's Dependency Management for Code Bundling

Review on pnpm

2023-02-15

pnpm

pnpm is a modern package manager for JavaScript that provides a fast and efficient way of managing dependencies for your projects.

Monorepo support

A monorepo is a software development approach where all code for multiple projects or packages are stored in a signel repository.

Similar to the workspace of npm and yarn, pnpm also support workspace well enough.

Monorepo's package version matching headache

In a monorepo, where multiple projects and services share a codebase, managing dependencies and versioning can be a headache.

To solve this, you may need carefully add dependencies and check if the same version is used across the packages inside monorepo.

Tools such as @manypkg/cli may help you a lot in this situation.

How pnpm resolve peerDependencies

How peers are resolved | pnpm

If you don't know about resolving peerDependencies on pnpm, You may encounter tricky issue to solve.

Simply to put, if a package has peerDependencies, the package can be installed twice or more.

So, if you want to add some library on you project, you need to carefully check that the package has peerDependencies.

Especially, the library requires multiples across project's workspace packages you have to ensure the same versions of peerDependencies are installed in using package inside workspace.

Why is the multiple installation matter?

The suprise come from when you try to bundle as a single application.

Since each workspace packages are using seperated dependency.

You may see something like next image.

As you can see @mui/material included twice.

Because @mui/material has peerDependencies of @emotion/*, and if you don't match those version on each workspace package's package.json, differnt version installed and bundled together.

How to fix

First, install the same version of peerDependencies on each workspace's packages.

And ensure the same version is installed across workspace by adding override in package.json.

  "pnpm": {
    "overrides": {
      "@emotion/react": "^11.10.6",
      "@emotion/styled": "^11.10.6",
      "@mui/material": "^5.10.16",
      "@types/react": "^18.0.26",
      "react": "^18.2.0",
      "react-dom": "^18.2.0"
    }
  }

And result would be like next image.

Loading script...