Nx Implicit Libraries: The Hidden Gem πŸ’Ž

Younes
Marmicode
Published in
5 min readJun 18, 2024
Nx Implicit Libraries: The Hidden Gem
🎬 Watch it in action!

In order to leverage the tremendous capabilities that Nx provides, it is common to split applications into multiple libraries. In fact, among other benefits, splitting applications into libraries offers clear separation of concerns and boundaries, as well as faster task execution thanks to Nx caching, graph, and parallelization.

However, as you create more libraries, you will notice some duplicated configurations across libraries.

These files can clutter your workspace and discourage you from creating more libraries.

Here is an example of a freshly generated web library:

libs
└── web
└── catalog
└── ui
β”œβ”€β”€ README.md
β”œβ”€β”€ src
β”‚ β”œβ”€β”€ index.ts
β”‚ └── lib
β”‚ β”œβ”€β”€ catalog.spec.ts
β”‚ └── catalog.ts
β”œβ”€β”€ eslint.config.js
β”œβ”€β”€ project.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ tsconfig.lib.json
β”œβ”€β”€ tsconfig.spec.json
β”œβ”€β”€ vite.config.ts
└── vitest.config.ts

πŸ’Ž Project Crystal

Since version 18 (and actually a little before that), Nx has been able to infer tasks based on the project structure. This means that Nx plugins can automatically add new targets (e.g., implicitly add a test target with the right configuration when it detects a Vitest configuration file). This is called Project Crystal.

This reduces duplication in project.json files and allows a more centralized configuration.

Before Project Crystal

Before Project Crystal
Before Project Crystal

After Project Crystal

After Project Crystal
After Project Crystal

πŸͺ„ Implicit Libraries

Project Crystal reduces the amount of duplicated configuration in project.json files. But what if you could remove the project.json files altogether?

Using Nx inference, you can create your own plugin to add nodes to the Nx graph (e.g., declare libraries) or enrich existing nodes (e.g. add targets). Considering that the remaining information in the project.json files can easily be derived from the project structure (assuming there is a convention), you can infer the remaining information in project.json and then simply remove this file.

Implicit Libraries
Implicit Libraries

πŸ“‚ Shared Configurations

We have managed to remove the project.json files from the libraries, but what about other configuration files such as eslint.config.js, tsconfig.json, vite.config.ts, vitest.config.ts, etc.?

While it is tempting to completely remove these files as well, you should not, as they are still useful for other tools and IDEs (e.g., IDE lint plugins, test runners like WallabyJS, etc.).

However, since most libraries within a specific group share similar configurations, you can relocate these configuration files to the parent group directory. In the previous example, this would be the libs/web directory. This way, IDEs, and other tools will still be able to pick up the configurations.

🎯 Implicit Libraries’ Targets

After removing the project.json and replacing configuration files with shared configurations, most Nx built-in plugins will not be able to infer the target configurations.

You will have to adapt your Implicit Libraries plugin to not only create the libraries but also add the necessary targets as well.

Implicit Libraries Targets
Implicit Libraries Targets

Make sure to engineer your shared configurations and targets properly to ensure that the tasks are only run on the library’s files.

It is worth mentioning that some tools (i.e., Eslint & Vitest) just need to be executed with the library’s root as the current working directory:


{
...,
targets: {
lint: {
command: 'eslint',
options: {cwd: projectRoot},
...
},
...
}
}

🏷️ Inferred Tags

Your Implicit Libraries plugin is aware of your project structure and conventions. It can easily add tags to help you enforce boundaries or simply filter tasks to run.

This will prevent libraries from being mistakenly tagged and ensure that your project structure reflects library categories.

Implicit Libraries Tags
Implicit Libraries Tags

πŸ—οΈ Implicit Libraries Generators

While generators might sound useless for Implicit Libraries, they still make sense as they can be used to update the paths in the tsconfig.base.json, and simply prompt the developer for the right categories (e.g. platform, scope, type) in order to generate a valid library path.

🧩 Challenges and Gotchas

While Implicit Libraries are a great way of reducing the amount of configuration files in your workspace, and encouraging developers to create more libraries, you must be aware of the related challenges:

  • Most Nx built-in plugins rely on the project.json file to infer the targets configurations. This means that you will have to adapt your Implicit Libraries plugin to add the necessary targets.
  • It is not always easy to control all the options of a tool using target options. For instance, there is currently no Vitest option to override the cache directory. The workaround is to use the current working directory to compute it but this can interfere with Nx batch mode.

πŸ“– Marmicode Cookbook

If you want to learn more about Nx and more, check out the Marmicode Cookbook!

The Marmicode Cookbook

πŸ“š Additional Resources

--

--

Younes
Marmicode
Editor for

Software Cook, Teacher & Coach Google Developer Expert for Angular Nx Champion