Typescript monorepo with yarn workspace

Typescript Monorepo setup you will likely enjoy.
profile photo
Adam Pietrasiak
I know there are plenty of solutions for managing monorepos, Lerna, and so on. To be honest, I am not checking those anymore.
Our setup (e.g., at https://screen.studio) is, I believe, very simple and effective. I set it up, I think, 4 years ago and have never looked back.

Typescript, bundling, libraries, and apps

At the core of our setup, we have the concept of libraries and apps.
App is something the end user interacts with. In our case, it is our website and our Electron app.
Apps are responsible for bundling libraries. Libraries are simply buckets of code. Libs have no build pipelines; they don’t even have a src folder. They are flat, with very simple package.json and TypeScript files. No configs, no build scripts, and no type definitions (more on that later). Apps will be responsible for building libs.

Core packages config

At the core, we have package.json like this:
Image without caption
And then each package have package.json like this
Image without caption
Believe it or not - this is the entire package.json of quite a huge part of our codebase.
You could technically say it has no dependencies defined, which is not a good thing. I kind of agree, but I think out of laziness, I usually add dependencies to the root package.
Now, you run yarn install, and magic starts to happen.
@s/ui is moved to node_modules/@s/ui, but it is not copied there - it is symlinked, so technically <repo>/ui folder is mirrored with <repo>/node_modules/@s/ui - every change that happens in the source file is also present inside node_modules. This is important, as it allows for a great hot reloading experience, etc.
But note, that inside node_modules we have .ts files, which are not bundled at all - those are source files.
Now, you simply import those like:
Image without caption
It just works. It is fully typed and hot reloaded. You don’t need tsconfig imports magic to make root import work. It works because our package is mirrored into node_modules/@s/ui. It does not require .d.ts files at all, because there is no src or dist folder, so it simply reads types directly from the source code.
The only thing you have to do is to define a proper bundling config, as often by default bundlers expect things in node_modules to already be bundled.
For example, our app called web is using next.js and our next.config.ts needs something like this:
Image without caption
And that’s it. Next.js now knows that it needs to transpile those TypeScript modules when they are imported. Hot reloading works out of the box. Any change inside our ui package is instantly reflected when browsing localhost, there is no need to rebuild, update type definitions etc.

Some other tricks

At the root package.json, we have scripts like those:
Image without caption
This allows you to manage the entire monorepo from the root folder. For example, our web package has its own development script that will start the Next.js development server.
So from the root you can do yarn web dev and it will just work. Or if you need to add some dependency only to the web package, you do yarn web add some-package

Yarn 4.5 and corepack

We try to use the latest yarn version. Our goal, however, is to make the onboarding developer experience as smooth as possible.
Not sure if you’re familiar with it, but corepack enable is a really powerful Node command. With this one command (which is available already if you have Node installed), it will replace your global Yarn with the local one defined in the package. Thus, you can do yarn set version 4.5.0 --yarn-path, and it will create a plug-and-play copy of Yarn 4.5 inside your repo, creating .yarnrc.yml like this:
Image without caption
And you’re good to go. In your README, your Getting Started section can look like:
  • The only requirement - have nvm installed on your machine
  • Clone repo
  • run nvm install (assume you have .nvmrc which you should)
  • run corepack enable to make sure you will use yarn ”binary” which is inside the repo
  • run yarn install
  • optional - get your .env file from your colleagues
  • run yarn app dev or yarn web dev
  • enjoy coding
Related posts
post image
When the same bug is caused by multiple issues and only fixing all of them at once will make it go away
post image
Don’t increase your Electron app code complexity as you add more windows to it
post image
Due to a simple bug, Screen Studio app did generate over 2 petabytes of network traffic
Powered by Notaku