🚄Node On Rails: Creating a Monorepo aka workspaces with yarn
Tags: javascript, beginners, webdev, tutorial
Published: 2020-01-08 20:34:47

How do you structure a project that is modular and has many dependencies? Also, you are responsible for releasing it. You need to test, build, and publish all of them?

One of the solutions for this is to create a Monorepo!

### Node on Rails development structure

The goal for node-on-rails is to be modular. In the Javascript/Typescript world, this means to separate them into packages. Every module/component/plugin name it, as you want, will be its small package. At the start, there will be only two packages the `cli` package and the `core` package. The two will not be alone for a long time, and the build process and publication should be easy. So okay at some point, we can have `N` packages, but we want just one repo for it!

### What is a Monorepo?

Let's have a look what Wikipedia is saying:

> In revision control systems, a Monorepo is a software development strategy where code for many projects is stored in the same repository. As of 2017, this software engineering practice was over a decade old but had only recently been named.

Okay, that helps a little bit, but not really 🤷‍♂️.

Monorepo can mean a lot, and you can see different types of them out there on GitHub. Let's go through some kinds of Monorepos:

- A Company Monorepo: The most famous Monorepo lives at Google. According to insiders, every line of code at google is in this Monorepo. Billions of lines of code in one repo! Crazy. 

- A Project Monorepo: Here, you have all the code needed for your project. Backend, Frontend, Scripts, and everything else needed for that specific project. This can be documentation, configs, and many other things. This style of Monorepo is a good fit if you have a product and want everybody for
 that project to have all the information and code needed with one single clone

- A Package Monorepo: The Monorepo where you have a collection of (npm) packages. All the packages are part of a bigger system. You can have all parts of the system in its package, and you can release every package on its own. You manage them all in on repo.

There are probably more types of Monorepo's.

It should now be clear what type we will use for node-on-rails. The 'Package Monorepo'.

### How to set up a Monorepo?

For now, we will use `yarn workspaces`. There is also `Lerna`, which is probably the most popular Monorepo tool. If needed, we will add it later.

The first thing we need to create is a root folder. 
```
mkdir node-on-rails
```
In the newly created `node-on-rails` folder, we need to create a package.json file with the following JSON inside:

```JSON
{
    "private": true,
    "name": "node-on-rails",
    "workspaces": [
        "packages/*"
    ],
}

```

The "private" key will prevent us from publishing the root package to the public. The name is optional, but I still like to add it. 

The last three lines are the most interesting here. This is where we define our workspaces. It is an array of folder paths. All of our packages will be in the `packages` folder so we can use the `*` operator to tell `yarn` that we want all subfolders to be a workspace.

Let's now create our two first package folders with:
```bash
mkdir -p packages/CLI packages/core
```
To keep this post short, we will create one of the package.json's, but you can, for a start, copy and paste it.

Now we will create a `package.json` on the `node-on-rails/packages/core` folder. with the following things inside:
```JSON
{
  "name": "@nor/core",
  "version": "0.0.1",
  "dependencies": {
    "typescript": "^3.7.4"
  }
}
```
You can do the same in the `node-on-rails/packages/cli` folder.

Let's install all the dependencies:
```bash
yarn install
```
Yes! That's it. This will install all the dependencies on all the workspaces!

If you now want to run a npm script in a workspace you can either `cd` into it or do the following:
```bash
yarn workspace @nor/CLI run test
```
or if you, for example, want to run all tests in all packages you can enter:
```bash
yarn workspaces run test
```
### Bonus: Update all npm dependencies
If you don't want to update all your package by hand, you need to install
`npm-check-updates` with:
```bash
sudo yarn global add npm-check-updates
```
and add the following script to your root package.json
```json
    "scripts": {
        "upgrade:all": "find . -type f -name 'package.json' -not -path './.git/*' -not -path '*/node_modules/*' -execdir ncu --upgrade \\;"
    },
```

That is all for this post. I hope you now have a better understanding of what a Monorepo is and how to create one.

If this added any value for you, please consider sharing this post on twitter or any other social media. I would be the happiest person on earth.🙏😀

**👋Say Hello!** [Instagram](https://www.instagram.com/lampewebdev/) | [Twitter](https://twitter.com/lampewebdev) | [LinkedIn](https://www.linkedin.com/in/michael-lazarski-25725a87) | [Medium](https://medium.com/@lampewebdevelopment) | [Twitch](https://dev.to/twitch_live_streams/lampewebdev) | [YouTube](https://www.youtube.com/channel/UCYCe4Cnracnq91J0CgoyKAQ)