Why I Love Nrwl Nx and Why You Should Too ;)
Tags: javascript, nx, devops, development
Published: 2024-02-19 15:01:32

🤖 Disclaimer: 🤖
I wasn't the person who introduced Nx to our project. Here is a huge shout-out & kudos to Damian Bielecki. I joined the project that was already up and running. 

And to be honest, initially, I was not convinced. A monorepo sounded counter-intuitive to me. WHY one big repo for many apps? 🤔 Sounds like a developer's nightmare for maintaining and management. And probably it can be, when you do this without the right strategies and right tools. 
**Nx is our right tool**

![Nx is the way](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzlc03yac3566jzis97i.png)

## So, what exactly is a monorepo?
First off, our repository is what's known as a "**monorepo**". This means that instead of managing multiple apps and libraries across separate repositories, we handle them all within a single repository. To effectively manage our monorepo, we use Nrwl Nx.

Nx tools provide us with the capabilities to run only the projects that are affected by changes, cache results, and more. 

## Applications and Libraries

In a monorepo, applications and libraries are 2 basic components.

### Application:

- can be transformed into a deployable artifact
- holds configurations for its building process
- holds configurations for running its tests
- can utilize code from libraries

### Library:

- consists of code that can be utilized by applications or other libraries, can utilize code from other libraries
- holds configurations for running its tests

Example 

```
📦.
 ┣ 📂apps
 ┃ ┣ 📂 auth-service
 ┃ ┣ 📂 management-service
 ┃ ┣ 📂 web-service
 ┃ ┗ subs-service
 ┃   ┣ 📂 sls
 ┃   ┣ 📂 sls-api
 ┃   ┗ 📂 sls-e2e
 ┣ 📂libs
 ┃ ┗ 📂 shared
 ┃   ┗ 📂 utils
 ┗ 📂tools
   ┗ 📂 generators
```
As you see monorepo includes several applications and libraries (and could be more... like tools).


Suppose you update a library in your project. 
Naturally, this library might be used by two or more apps (or microservices etc.). In such cases, you need to test the change against those dependent apps to ensure the updated library is backward compatible.
As a developer and a human, I'm aware that my thought process and workflow can sometimes be unreliable. Although the app is well-covered with tests (let's even say perfectly, following the test pyramid), if you have many dependent apps, you still need to remember to update the lib version, run those tests, and sometimes you might forget about that one little-used service somewhere.

With Nx, this is no longer an extra task for my brain. Nx automatically runs the projects affected by your changes. So, when you update something, Nx identifies all the code impacted by this change and automatically runs tests for those projects for you.

![nx affected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wtu0lm9i2ietb70nv186.png)

Adding a little magic to the mix, you can check which projects are affected by your changes with a simple command - `nx affected` - and even see a cool visualization of the affected projects as a graph. 

This reassures us that releasing code, which alters several applications at once, won’t result in any breaking changes. This is not just a nice-to-have; it's a massive improvement, especially when it comes to deploying. You know exactly what needs to be deployed together with the new changes.


## Versioning simplified
In my previous organization, I witnessed firsthand navigating through the versioning chaos. It was a struggle, maybe not daily, but frequent enough to notice. 

**Example:** you bump a library version in one repo, then you need switch to 3 different repositories to ensure the update is applied. But only to those projects that are still being maintained – and that's assuming you're in the loop of knowledge and have the needed access. 


![version bump across repos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rx1o8rmis79sumyuxwjd.png)

Even with a tight process, up-to-date documentation, and checklists in check, it wasn’t uncommon to find deprecated functions still being used, long after they should have been phased out.

With Nx in our monorepo setup, things are starkly different. Every app within the monorepo uses a single version of a dependency. And... this dependency **gets updated automatically with every merge to master**, ensuring all projects are on the same page. That means significantly less risk of running into unexpected breaking changes. No more energy wasted on manually bumping library versions across multiple repos. 
No more cluttered `chore: version bump` commits. 
Everything updates in unison, saving us time.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g5utggchrpsuu2g3cvzv.png)


## Nx Cloud
I need to mention Nx Cloud too. Nx Cloud literally boosts project by its caching capabilities.  

- Caching is caching, what could be so cool here? 🤔

Nx Cache stores the output of our operations and reuses it if there are no changes. This way ensures that only the necessary work is done. The rest is either skipped or retrieved from the cache. This caching works across the board, no matter what tools we use for building, testing, or linting.
It also caches all terminal output when running tasks, so if a task's results are fetched from the cache, you'll see the terminal output as if the task had just been run.

#### 💻 Time for a practical example: 
So, during a deployment, if **we've already built and packaged the application** (like the last run on your env), Nx Cloud ensures for us there's **no need to repeat these steps. They're fetched from the cache instead.** (Cache hit less than 1s)
Then the deployment is executed to ensure it’s up-to-date, given it's a step that could have been modified since last run. Take a look 👇


![Nx Cloud runs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4alq7yqjmv3dw10lkwgb.png)

The criteria for what makes a cache valid or not is configurable. For anyone curious about the nitty-gritty of how Nx Cloud's caching works, the Nx documentation is a great resource.

## Generators
In my experience, setting up development workspaces for a new application, then develop new endpoint could take up to week. With Nx, this process can be shortened to less than a day. Nx Generators enable you to create or modify your codebase in a straightforward and repeatable manner. 

You can generate an entire project with a serverless lambda setup (which we use in our team, again huge kudos for Damian 👏👏👏) or choose from other ready-to-go configurations provided by Nx. This reminds me of the Rails generators I missed in the Node.js stack, but Nx has more than made up for it 💜 


Huge capabilities in free tier - so, give it a try if you still wonder ;D