DEV Community

Cover image for pnpm and Parcel based monorepo
Zuri Klaschka (they/them)
Zuri Klaschka (they/them)

Posted on

pnpm and Parcel based monorepo

The problem

I have tried several ways of managing JavaScript/TypeScript Library Monorepos in the past: lerna, yarn workspaces, etc.

Now don't get me wrong: These are great tools and I very much appreciate the effort their authors have put into them.

But they always felt a little bit like gambling. It never felt like I was really in control of what was happening (with a lot of black magic), and I found that they felt a bit ... fragile (I was alsways worried about breaking some symlinks or stuff like that when running any commands).

A solution?

I wanted to try both pnpm and Parcel. I had heard good things about both tools and have recently gotten more and more frustrated with their more established competitors.

When I looked at their respective documentation pages, it looked like both had great monorepo support. Since I was also still on a long-lasting search for some "building an npm library"-compatible monorepo solution with a better developer experience than what I had seen so far, I decided to give it a shot.

The repository

So, I built (and documented) a test repository to try this new monorepo setup:

GitHub logo pklaschka / pnpm-parcel-monorepo-test

A repository for trying a JS/TS npm library monorepo setup using pnpm as package manager and parcel as a build tool.

pnpm & parcel monorepo test

A repository for trying a JS/TS npm library monorepo setup using pnpm as package manager and parcel as a build tool.

Development prerequisites:

Tech Stack

This is an overview of the most important components of this monorepo's tech stack

Usage

Setting up the development environment

Install the dependencies:

pnpm install
Enter fullscreen mode Exit fullscreen mode
  • automatically runs recursively for the workspace, cf. https://pnpm.io/cli/install
  • Alias: pnpm i
  • npm ci-equivalent: pnpm i --frozen-lockfile (automatically true in CI environment)

You can also run pnpm install when anything about your dependencies becomes out of date to fix it back up.

Dependency Management

Installing

The repository contains a test setup with a more or less full tech stack consisting of, among others:

  • TypeScript
  • ESLint
  • Prettier
  • fliegdoc (a self-built documentation generator)
  • jest / ts-jest
  • GitHub Actions

I described most things in the README.md, but I also created an additional public Notion page describing more details.

Results

I'm really happy with how it works and will definitely use this approach in the future. I'll also probably migrate existing monorepos to this approach, in the future.

Advantages

  • 🟢 you feel like you're in control with pnpm, it's pretty straight-forward to understand how their workspace system works, so you feel like you're in control and don't have to guess about fixes to your problems 🎉. E.g., pnpm install sets up everything. Before, I always was unsure if I should now run npm install, lerna bootstrap, or something else.
  • 🟢 quick build times since parcel builds all the packages at once (instead of running build scripts one package at a time), build times (especially with the build cache in place) are incredibly fast
  • 🟢 development experience with parcel watch, it's possible to very quickly develop
  • 🟢 "native" workspaces working with workspaces / multiple packages feels "native" to pnpm (compared to its competitors, where I unfortunately found that it feels more like a "hacky side feature"). Commands work how I would expect them to work, "internal" dependencies betweeen packages automatically get hydrated with version numbers on publish, and so on.

Drawbacks

Of course, every approach comes with a few drawbacks. Here are the ones I've found so far:

  • 🟡 less ecosystem support while pnpm and parcel work great in 99 % of cases, tools often don't test their support for these as much as, for example, for yarn and webpack
  • 🟢 (no Dependabot support) at the time of writing this, GitHub's Dependabot doesn't support pnpm. Thankfully, Renovate seems to work well.
  • 🟢 (no included "release automation" tooling) lerna came with great Changelog / Conventional Commit / ... based release automation tooling. Unfortunately, I haven't yet found a great solution for doing something similar with pnpm. Do you have any recommendations?

A quick fix for a Parcel bug that almost made me dismiss it

When I initially tested Parcel, it felt unstable. It wouldn't shut down, would from time to time just overwrite my package.json, and just overall not work very well at all.

I was almost ready to give up when I found this issue on GitHub. It turns out that I had a package-lock.json somewhere higher up the file tree (probably some backup I had created before). This lead to Parcel showing all kinds of weird behavior (not only the one described in the issue). So if you decide to try this approach and feel like Parcel is "freaking out" in a weird way, it might be worth checking for package.json, packaage-lock.json or similar files higher up in the file tree.

So overall, this is easy to fix. But this almost made me (which would have been a shame!) turn away from Parcel, so I wanted to include this note here.

Even more details

Furthermore, I've documented everything I learned about the process / how the repo is structured in a Notion Page. If you decide to try this monorepo configuration, this could be useful to you as it includes all the commands you need to know, links to various important resources, and so on.

Author

Top comments (3)

Collapse
 
llbbl profile image
Logan Lindquist

I like pnpm!

Collapse
 
kennybll profile image
Kenneth Bennett

Have you looked into nx.dev or turborepo? I've been using nx and noticed some lack of control, especially with some community based plugins.

Collapse
 
pklaschka profile image
Zuri Klaschka (they/them)

Thanks for your comment!

For nx.dev: I had looked into it, but decided against it. While nx looks really cool, it felt like that weird combination of having "too little" (the tool is pretty opinionated about how everything should be structured, e.g., with the --publishable flag and how essentially the entire repo is then controlled by nx) and "too many" (skimming through their documentation didn't really give me an overview of everything nx could do) options at the same time.

Based on that, I think nx is (probably; I haven't tried it 😉) a great solution for a big internal project with an engineering team onboarded onto the project. My use case is an open-source project (i.e., contributors who don't have in-depth knowledge about all the build tools), which is why I decided against it. I didn't feel like I would have been able to write a comprehensive enough, yet short CONTRIBUTING.md if I had used that.

Also, I actively dislike tools where I have no clue what's going on. I'm sure it's possible to learn nx enough to understand what's happening. But not in the amount of time I currently have available for that 😜

For Turborepo: This definitely looks cool. While I had taken a quick look at it, I didn't really look into it in detail (as I had already found the solution presented in the article and was happy with it).

Personally, I tend to dislike tools trying to "solve everything" (I've seen too many tools trying to solve everything and then being unable to handle the complexity of that). While turborepo seems to be a bit better in this regard, the fact that their Getting started section shows building a "pipeline" with building, testing, and linting was what turned me off when I initially looked into it. This is just personal preference, though.

Overall, I would say that I looked at (but not deeply into) both of them but (for my use case) they felt like they tried to solve too much for my taste. Don't get me wrong: I think both of these tools are great and have their advantages, but especially with nx, I feel like it doesn't really work in an environment with a lot of inexperienced contributors. And with turborepo, I haven't (yet 😉) found a need for it in my project. Maybe that day will come. But until then, I prefer to keep my tech stack for something as elementary as "Repo Management" / "building stuff" as small as possible (giving me a better chance of stuff not breaking and the ability to better understand what's going on if something breaks).