Skip to content

Commit 5a6c4b4

Browse files
committed
Tips on NX article
1 parent 9de0a9e commit 5a6c4b4

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

content/posts/nx_tips.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
+++
2+
title="NX tips"
3+
date=2023-05-29
4+
5+
[taxonomies]
6+
categories = ["Tips"]
7+
tags = ["NX", "Monorepo"]
8+
9+
[extra]
10+
comments = true
11+
+++
12+
13+
# Context
14+
I recently started working on trying to improve the development experience on the frontend part of my company.
15+
The goal was to be able to:
16+
* reduce the dependency management issues that we were having
17+
* co-localize the code to reduce friction between teams
18+
* reduce build time by using caches
19+
* share a common set of practice (linting, testing ...) with ease.
20+
21+
Basically we wanted to use a [monorepo](https://monorepo.tools/).
22+
23+
So I compared multiple tools:
24+
* [Turborepo](https://turbo.build/)
25+
* [NX](https://nx.dev/)
26+
* [Lerna](https://lerna.js.org/)
27+
* [Rush](https://rushjs.io/)
28+
29+
I won't go much into details about the differences between those tools, it's not the purpose of this article, but we ended up choosing NX.
30+
In the next part I will list some tips about how to use NX, and will probably update this article with new tips as I discover them.
31+
32+
# NX tricks
33+
NX as a pretty solid documentation, but sometimes I feel like it's missing some examples, that's why I am writing this article, for my future self.
34+
35+
## Running root level commands
36+
To run root level command, you can modify your `package.json` to add a script like this one:
37+
```json
38+
{
39+
"scripts": {
40+
"format": "nx run-many --target=lint --all --parallel"
41+
}
42+
}
43+
```
44+
This will allow you to run `npm run format` and it will run the `lint` target on all the projects in parallel.
45+
But what bothered me was that It forces developers to switch tool to run project level commands while the `nx` CLI would be used everywhere else.
46+
So I wanted to be able to run `nx format` instead of `npm run format`.
47+
To do so you can update your `package.json` with the following:
48+
```json
49+
{
50+
"nx": {},
51+
"scripts": {
52+
"format": "nx run-many --target=lint --all --parallel"
53+
}
54+
}
55+
```
56+
And voilà, you can now run `nx format` and it will run the `lint` target on all the projects in parallel.
57+
58+
Note that the opposite is also possible, to run everything through `npm` but keep the caching and parallelization of NX
59+
by prefixing commands by `nx exec -- ...`.
60+
61+
Full documentation is available [here](https://nx.dev/recipes/other/root-level-scripts).
62+
63+
## Defining common targets
64+
NX allows you to configure your monorepo packages in a `project.json` file (one per package).
65+
In my context, I wanted to define some common targets that would be used by all the packages,
66+
but I didn't want to copy/paste the same targets in all the `project.json` files.
67+
68+
So How can I share those targets but still be able to configure them per package if needs be ?
69+
70+
The answer is to use `targetDefaults` in the `nx.json` file (the global project configuration that is at the root of the monorepo).
71+
Here we could define our previous lint configuration like this:
72+
```json
73+
{
74+
"extends": "nx/presets/npm.json",
75+
"$schema": "./node_modules/nx/schemas/nx-schema.json",
76+
"targetDefaults": {
77+
"lint": {
78+
"executor": "@nx/linter:eslint",
79+
"options": {
80+
"lintFilePatterns": ["src/**/*.ts"]
81+
}
82+
}
83+
}
84+
}
85+
```
86+
Then we would need to update the `project.json` of each of the packages that want to use this target like so if no override are required:
87+
```json
88+
{
89+
"name": "my-package",
90+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
91+
"targets": {
92+
"lint": {}
93+
}
94+
}
95+
```
96+
But if we need to override parts of the target configuration, we can:
97+
```json
98+
{
99+
"name": "my-package",
100+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
101+
"targets": {
102+
"lint": {
103+
"options": {
104+
"lintFilePatterns": ["src/**/*.ts", "src/**/*.js"]
105+
}
106+
}
107+
}
108+
}
109+
```
110+
That's a good balance between monorepo global convention and specific configuration per package.
111+
112+
Unfortunately this feature is not well documented [here](https://nx.dev/reference/nx-json#target-defaults), but I managed to find
113+
an issue and an associated PR that explains what I told you before: https://github.com/nrwl/nx/pull/12435.
114+
115+
# Conclusion
116+
That's it for now, I am not sure if I update this article or create new ones / split this one in multiple articles in the future
117+
so keep an eye on my blog if you are interested in this kind of articles.
118+
119+
Flo.

0 commit comments

Comments
 (0)