Fresh and easy-to-understand dive through features of lastly popular Nx from the NRWL team. Let's create some applications and libraries!
One such tool is the NRWL Extension, or NX for short. In this article, I will introduce you to what exactly NX is, what are its uses and its most important features.
The basics of the basics
The NX (NRWL Extension) tool is a monorepo solution developed by NRWL team. NX provides a number of functionalities that allow for better organization, testing and distribution of code in large projects based on various JS technologies - Angular, React, Next.js, Nest.js and many others.
This tool provides, among others:
- Automation of development processes (creation of components and boilerplate)
- Support for creating monolithic and microservice architectures
- Support for unit testing tools and e2e (Jest and Cypress)
- Support for tools for automating building and distribution processes (Bazel and Nx Cloud)
- Support for code analysis and organization tools (ESLint and Prettier)
- Support for dependency management tools (npm and yarn)
NX also allows easy integration with other tools and libraries, such as NgRx, Storybook, etc. This allows developers to use already existing solutions and tools in their projects.
NX is useful for development teams that work on large, complex projects and want to increase their productivity by automating processes and better code organization.
NX use cases from NRWL
NX has many use cases. These are not just large projects with many dependent, shared libraries, but also work well for small projects.
What can this tool be used for?
- Creating a monorepo NX
- Lerna monorepo integration with NX
- Migration from a single Angular application to the NX workspace
- Creating a single Angular application or in another technology
- Create any JS project from package.json
The new monorepo with NX
To create a new workspace, all you really need is the installed npm package manager and the command: npx create-nx-workspace@latest, which will create a structure for us. At this link, you will find everything you need. After this command, you will get access to all functionalities of NX.
Lerna monorepo integration with NX
The Lerna integration with NX will allow as to:
- Concurrent execution of tasks
- Caching of operations
- Distribution of tasks
- Limitation of code building
Just update Lerna to the latest version and set the useNx flag to true in the lerna.json configuration file - migration video.
Migration from a single Angular application to NX workspace
Just install the CLI with npm i @nrwl/cli -D, and migrate with npx nx init in the second step.
Creating a single Angular or other technology application
In this case, NX provides a ready configuration of tests Jest, ESLint and Prettier at the start of the project, provides a mechanism for caching operations and limits building the code only to places where something has been changed.
To create any application, just run the npx create-nx-workspace@latest –preset=angular command. If you want to generate an application in React or another NX-supported technology, you need to replace the preset value as follows: preset=react.
Here is a list of currently supported:
Create any JS project from package.json
In this case, we can only use the script caching mechanism. Just install the CLI with npm i @nrwl/cli -D.
From now on, any script configured in the package.json file can be cached by NX by calling it in this simple way: npx nx [name].
Core NX features
The creators specify such functionalities as:
- The ability to use additional scripts (task executors)
- Caching tasks results
- Cache sharing
- NX graph
- Resource sharing during tasks (distribute task execution)
- Automatic update of dependencies
- Enforcement of dependency boundaries
Ability to use additional scripts (task executors)
We receive support and configuration of tasks within individual projects, as well as the entire monorepo. Task executors are used to automate various processes such as building applications, testing, updating dependencies, and many more.
For example, we can run the command: nx affected:build, building only those modules that have been modified since the last build.
If we want to run e2e tests based on changed files, we can run the command: nx affected:e2e.
Also the command: nx affected:lint will only run lint for files that have been modified since the last build.
These examples show how task executors can speed up development processes by focusing only on specific elements of the project that have changed since the last build or testing.
In addition, NX provides the npm package @nrwl/nx-plugin, which allows us to create our task executor. Thanks to this, we can extend the functionality of the NX tool and adapt it to our own needs.
Caching tasks results
NX uses a cache not repeatedly to build code that has already been made. In the context of this tool, cache sharing means that different libraries or scripts used in the project can use the same cache, storing information about compilation, file scanning, etc. This way these processes do not have to be repeated for each library or script which speeds up the construction process and increases efficiency.
How does the cache work in practice? Before running a given task, NX calculates the hash of the given library. If the hash is the same as in the previous call, it doesn't do the job again, just takes the result of the previous call.
Hashing in Nx
How to optimise cache?
Source code hash inputs - it can specify which files will be considered when building the hash.
Runtime hash inputs - it can specify additional parameters that will be substituted when starting the task, based on which the hash will be built.
The cache can be shared between multiple developers as well as CI tools, as part of a self-hosted service and in the NX Cloud.
All you have to do is connect to the NX Cloud with the command: npx nx connect-to-nx-cloud and the results of our tasks can be used by every member of the team.
Distributed caching in Nx
This graph allows you to visually explore dependencies in projects, libraries, and tasks that are within a monorepo.
All you have to do is run the command: npx nx graph.
This will open the browser and visualize the dependencies in the project. Viewing the entire graph can be difficult with large solutions. Therefore, NX provides additional filters that allow you to narrow down the visibility of dependencies. You can test the operation of such a graph at: https://nrwl-nx-examples-dep-graph.netlify.app/
Distribute task execution
This is support for delegating tasks to many agents and parallelizing their performance for even more effective work. This functionality minimizes the execution time of CI processes, along with maintaining the proper order of execution.
Distributed task execution can run on any CI provider. The developer is only responsible for configuring tasks in his CI. NX Cloud then coordinates how these tasks work together.
Integration with the IDE - NX Console is a UI for NX, which is made available in the form of plugins for such IDE's as VS Code, WebStorm or Neovim.
Here are the links to those plugins:
These plugins are not developed by NX Team but by contributors!
Automatic dependency update
NX CLI has a migrate command that allows you to quickly update NX and dependencies like Angular, React , etc.
This command prepares the migration script for all technologies that are to be updated. The next command performs the migrations. Finally, all you need to do is remove the migration file and update the main dependencies.
The entire migration is just 4 steps:
- Command: nx migrate latest
- Command: nx migrate –run-migrations
- Deleting the migrations.json file
- Command: npm install
Enforcing dependency boundaries
Appropriate configuration allows you to create rules that allow or block the use of given libraries or groups of libraries by others.
The whole concept is about tagging libraries and applications appropriately:
Then you need to write the rules in the ESLint configuration file:
After configuring the rules, just execute the nx lint command, or configure them as part of the CI, and we can be safe about proper dependency injection in our project.
Such groups can be layers or modules of a given solution.
If you liked it, be sure to visit us on Linkedin, where we regularly post programming content.