How to Easily Manage Dependencies in a JS Monorepo

Dependency management in a JavaScript monorepo is made much simpler with pnpm and Bit.

Dependency management in JavaScript is the number 1 pain for developers according to the 2021 “State of JS” survey. That’s not much of a surprise. Not far behind it in 2nd place, comes code architecture.

When you try to effectively manage dependencies in a monorepo you end up facing these two problems together at the same time. You’re basically up against a dependency Megazord. That can be a painful experience.

Monorepos can provide a better developer experience in some cases and advantages in terms of code-sharing in order to, in some cases, make development easier. Many companies from Goole and Uber to startups leverage a monorepo in certain cases to gain these benefits.

However, choosing a monorepo architecture comes with a price. It leads to many issues, especially at scale, that can make it increasingly hard to develop and maintain the software projects inside it.

Let’s take a close look at one of the most painful problems on monorepos: Managing dependencies. We’ll show how using a combination of open-source tools such as Pnpm or Yarn workspaces and Bit, this problem can be elegantly solved and make it much easier to work with dependencies in a monorepo.

Pains of managing dependencies in a monorepo

So why is dependency management in a monorepo painful even as you use a Yarn or Pnpm workspace?

We would expect that once the monorepo has only one dependency management system during development things will become much simpler. There is just one set of dependencies that every package in the monorepo has access to. But that’s a double edges sword. What works in development might not work in production and things can easily break. Let’s see how.

Phantom dependencies break the code when you publish

With Pnpm or yarn workspace every package in the monorepo has its own package.json and it dependencies are defined in it. Yet all dependencies in the workspace are in the root of the monorepo.

At first, this looks like a huge power boost: Every project or package in the monorepo as access to use every dependency library.

But what happens when a package you develop in the monorepo imports and uses a dependency it has access to, but that isn’t defined in its package.json?Then your tests will pass during development but will fail when you publish.

There are two ways to solve this; You can use a linter to alert you in real time that you are using a dependency’s code that’s not in your package.json or you can use a feature like pnpm’s isolated directory structure:

workspace
├── node_modules
│ └── .pnpm
│ ├── lodash@4.17.21/node_modules/lodash
│ └── ramda@0.28.0/node_modules/ramda
├── button
│ └── node_modules
│ └── lodash --> ../../node_modules/.pnpm/lodash@4.17.0/node_modules/lodash
└── card
└── node_modules
└── ramda --> ../../node_modules/.pnpm/ramda@0.28.0/node_modules/ramda

A similar problem arises with dev dependencies. Your project will run nicely and pass tests locally but when installed as a dependency it will break.

Dependency versions

Another huge pain is working with dependency versions in the monorepo.

The problem is that you might have a dependency (like Lodash or prettier) installed in the root, and a different versions in the package.json of the package you’re currently developing inside the monorepo.

The result is that your VSCode will “see” one version while when you publish the package it will use another version of the same dependency. The chance of breaking, in this case, is very high.

Solutions like manually checking versions are very time-costly and hard to do because the project keeps changing and so does every package in it. Automatic solutions and libraries can help but usually, come with a price as they blindly determine a single version regardless of consequences.

Solution: Yarn or Pnpm workspaces with Bit

Bit is an open-source project built for developing in components.

The Bit workspace add a virtual layer on top of your codebase that lets you develop and compose “components” which in this case are packages.

Bit solves many of the hard things about developing many packages in the same codebase, including the versioning and installation of dependencies — both those coming from inside and outside your projects.

When Bit is combined with pnpm, you get the most advanced and simple developer experience for working in a monorepo. In fact, Bit uses pnpm for installation under the hood and both mechanisms are developed by the same person in the open-source community.

How it works

Basically, once you develop in a Bit workspace you no longer care about the dependencies of the “component” (i.e. package) you work on. You also don’t care if they are dev or runtime dependencies or which version they’re on.

Let’s say you work in a Bit workspace and wants to add a new package in your monorepo called “new-lib”. You can create it as a component like this:

bit init
bit create node new-lib

Next you edit the code file and add an import statement to use Ramda:

import R from 'ramda';

export function lib() {
return 'Hello world!';
}

Now your code uses Ramda but you don’t have it as a dependency yet.

If you use bit-status you learn that you’re missing Ramda, and if relevant also React in case you want to render “compositions” (visual examples) of the component. Let’s say you want to add both.

Just run:

bit install react ramda

Bit’s workspace “knows” which component is missing these dependencies and will add it accordingly. You don’t need to specifically define it. Furthermore, Bit will “know” if it’s a dev or runtime dependency and add it accordingly.

Radical, isn’t it?

Then run bit show new-lib and Bit will tell you which dependencies it has and which are dev or other dependencies. Here’s an example (where new-lib is named just ‘lib’):

Dependencies no longer used in your code

What happens when you stop using a dependency in your code? Removing the import statement? Then Bit “knows” it’s no longer used in your code and it will remove it without you having to manually do it (like with pnpm/yarn workspaces without Bit).

When you remove an import statement you don’t always know if this dependency is used in another file, so being a responsible developer, you just leave it there. With Bit added that’s no longer a problem.

The only thing you’ll need to do manually is to decide if to remove a dependency from the workspace completely. At the package level, Bit abstracts away this work completely.

Test dependencies

When a dependency is used in the tests of a package but not in the code, and it’s installed in the workspace, without Bit you would need to install it as a dependency of the package. With Bit, as long as the dependency is defined in the workspace, you don’t need to. Run bit show new-lib After adding the dependency to the tests and see that its defined for the component.

Dependency version

Unlike in a traditional workspace, in a Bit workspace you list all your dependencies in a single place, in the workspace.jsonc file. After you run bit install ramda, this is how the dependencies section in your workspace.jsonc will look like:

"teambit.dependencies/dependency-resolver": {
"packageManager": "teambit.dependencies/pnpm",
"policy": {
"dependencies": {
"ramda": "0.28.0"
}
}
},

Sometimes, you might need to have a different version of ramda in some of the packages. In this case, in a traditional workspace you would use other versions of ramda in some of the package.json files. In case of Bit, you may use variants to configure groups of components. For instance, if you need to use "ramda@0.27" for any package that is inside the ui directory, use this configuration:

"teambit.dependencies/dependency-resolver": {
"packageManager": "teambit.dependencies/pnpm",
"policy": {
"dependencies": {
"ramda": "0.28.0"
}
}
},
"teambit.workspace/variants": {
"{ui/**}": {
"teambit.dependencies/dependency-resolver": {
"policy": {
"dependencies": {
"ramda": "0.27.0"
}
}
}
}
},

How is that possible?

Bit isn’t a package manager. It plays with pnpm and actually uses it.

A Bit workspace has no package.json for components (packages) in it. Instead, it dynamically generates the package.json files and passes them directly to the package manager, using its programmatic API. This is handled by the dependency resolver aspect. pnpm is used as the package manager and you can change to Yarn in the workspace.jsonc file.

Watch live demo:

Note: This post was merely an introduction to this awesome post by the creator of pnpm and core Bit developer Zoltan Kochan. All credit goes to him. Read the full blog post below:

Painless monorepo dependency management with Bit


How to Easily Manage Dependencies in a JS Monorepo was originally published in Bits and Pieces on Medium, where people are continuing the conversation by highlighting and responding to this story.

Leave a Reply

Your email address will not be published. Required fields are marked *

Instagram

Why do People Say: "Developers are Lazy"?
The saying “work smart, not hard” is applicable for programmers.
.
https://hackernoon.com/why-do-people-say-developers-are-lazy

.
Author: Aga Wozniak
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...

Mitigating the DDOS Threats Facing Banks and Fintechs
As much as digitization and cyber simplified banking, the Fintech sector has left digital payment activity exposed to malicious and suspicious activity.
.
https://hackernoon.com/mitigating-the-ddos-threats-facing-banks-and-fintechs

.
Author: Josh Horowitz
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...

24 Best JavaScript Blogs and Websites
In this overview, we have compiled a list of popular sites, as well as JS blogs that are worth reading and keeping in your bookmarks.
.
https://hackernoon.com/24-best-javascript-blogs-and-websites

.
Author: natashatsybliyenko
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...

The Projects Working to Lower Ethereum Gas Fees
As more investors try their hand at DeFi, gas fees are shooting over the roof, making engaging with decentralized apps uneconomical for most users.
.
https://hackernoon.com/ethereum-gas-fees-are-there-any-projects-working-to-optimize-eth-gas-fees

.
Author: CryptoVirally SLR
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...

On the Edge of a New Year: IT Predictions for 2022
The single biggest cause of network errors are people.
.
https://hackernoon.com/an-interview-with-uplogix-ceo-lisa-frankovitch

.
Author: Mignonette Garnier
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...

How to Modernize IBM i Applications
If you’re like most IBM i users, you know how much value your IBM i data and applications bring to your business. Your end-users, however, may not. In today’s world of rich user experience, fast-paced application development, and constantly evolving customer expectations, IBM i applications are unde…
.
https://hackernoon.com/how-to-modernize-ibm-i-applications

.
Author: Lansa
.
.
.
.
.
#blog #100Daysofcode #javascript #vuejs #datascientist #peoplewhocode #learntocode #coding #developerlife #frontenddeveloper #backenddeveloper #fullstackdeveloper #developer #webdeveloper #thedevlife #phpdeveloper #computerscience #programmer #programmingisfun #codingdays
...