As your codebase grows, so does the complexity of managing multiple apps and libraries. At this point Nx can help with its graph, but more importantly it can orchestrate all builds and tests in monorepo and keep you sane while managing dozens of packages.
In essence Nx is capable of running tasks in parallel based on what has changed from the previous commit. It also respects dependencies, ensuring that libraries needed by others are built first.
Key Features
Project Graph & Dependency Awareness
Nx automatically analyzes your workspace and builds a project graph, understanding how your apps and libraries depend on each other. This
allows you to build or test only what has changed and furthermore what is directly influenced by it, based on the changes between the current and the previous commit.Code Generation
Nx provides some nice generators for scaffolding new apps, libraries,
etc. I found them to be decent for Vue, but if you like it your way you can of course just ignore them.Advanced Caching
Nx caches build and test results, so repeated commands are lightning
fast. It can even share cache results across CI runs and between developers (Caution: sharing is a nice but paid feature - still very useful for enterprise clients).Powerful CI/CD
Nx can run tasks in parallel, only for affected projects, and provides detailed output for CI pipelines.
How to Configure Nx in Your Monorepo
Install Nx
If you’re starting from scratch, you can create a new Nx workspace with:
pnpx create-nx-workspace
In an existing monorepo, install Nx as a dev dependency and run init
:
pnpm add -D nx
nx init
Nx Workspace Structure
Nx expects some sub-directories with package.json
or it's internal project.json
file by default as a marker of a package. Sample structure can look like this:
/
├── apps/
│ └── app_1/
├── libs/
│ └── commons/
│ └── ui/
├── nx.json
├── workspace.json (or project.json or package.json files)
├── tsconfig.base.json
├── pnpm-workspace.yaml
└── package.json
- apps/: Applications (SPA, SSR, etc.)
- libs/: Reusable libraries (UI, utilities, etc.)
- nx.json: Nx-specific configuration (project graph, tasks, etc.)
-
workspace.json: Project definitions (can be split into per-project
project.json
orpackage.json
), - pnpm-workspace.yaml: Defines workspace packages for pnpm
Adding Nx Plugins
Nx supports plugins for frameworks and tools. For example, to add Vue support:
pnpm add -D @nx/vue
Or for Storybook:
pnpm add -D @nx/storybook
With the mentioned plugins you can run and utilize Nx commands for these frameworks, but also use them for scaffolding new projects.
To start with using commands as well as Nx packages I recommend the vscode plugin Nx Console. It’s a great tool for exploring available options and features.
Basic Nx Commands
- Run a target:
pnpm nx build:staging @monorepo/app_1
pnpm nx lint @monorepo/commons
- Run for affected (changed from the last commit) projects only:
pnpm nx affected -t build:staging
- Start the project graph:
pnpm nx graph
- List of installed and available plugins:
pnpm nx list
graph
It helps you visualize the dependencies between your packages. If you want to categorize your packages correctly in this browser based tool, I recommend either generating workspace.json
or a bunch of project.json
files, or as in my case (the simplest one) just adding this to your package.json
files:
{
"name": "@monorepo/ui",
"version": "1.0.0",
// ...
"nx": {
"projectType": "library" // or "application"
}
}
affected
Running locally the affected
command will work with default settings only if creating branch and making some changes as it compares your branch to the main
. But you can always explicitly compare the current state with a state from a couple of commits ago for test purposes.
# run lint for packages which changed
# between the current state and the state from 5 commits ago
pnpm nx affected -t lint --base=HEAD~5 --head=HEAD
This is the result of running lint for all packages in my monorepo template.
Not very spectacular, I know, but imagine how much build time you can save with a big monorepo while running this command on your server and executing commands in parallel only for the changed parts!
This is the last article in this series. If you want to learn more about creation of monorepo with Vue, check out other tutorials. If you prefer starting with a solid foundation - try this template, where I’ve put all of this into practice.
Top comments (0)