Using Nx Core Without Plugins
The core of Nx is generic, simple, and unobtrusive. Nx plugins, although very useful for many projects, are completely optional. Most large Nx workspaces use plugins for some things and don't use plugins for others.
This guide will walk you through creating a simple Nx workspace with no plugins. It will help you see what capabilities of Nx are completely generic and can be used with any technology or tool.
Using Nx Core
Creating a New Workspace
Running yarn create nx-workspace --preset=npm
creates an empty workspace.
This is what is generated:
packages/
nx.json
workspace.json
tsconfig.base.json
package.json
package.json
contains Nx packages.
1{
2 "name": "myorg",
3 "version": "0.0.0",
4 "license": "MIT",
5 "scripts": {},
6 "private": true,
7 "devDependencies": {
8 "@nrwl/cli": "12.8.0",
9 "@nrwl/tao": "12.8.0",
10 "@nrwl/workspace": "12.8.0",
11 "@types/node": "14.14.33",
12 "typescript": "~4.3.5"
13 }
14}
nx.json
contains the Nx CLI configuration.
1{
2 "extends": "@nrwl/workspace/presets/npm.json",
3 "npmScope": "myorg",
4 "tasksRunnerOptions": {
5 "default": {
6 "runner": "@nrwl/workspace/tasks-runners/default",
7 "options": {
8 "cacheableOperations": ["build", "lint", "test", "e2e"]
9 }
10 }
11 }
12}
Finally, workspace.json
lists the workspace projects, and since we have none, it is empty.
Creating an NPM Package
Running nx g npm-package simple
results in:
packages/
simple/
index.js
package.json
nx.json
workspace.json
tsconfig.base.json
package.json
The generated simple/package.json
:
1{
2 "name": "@myorg/simple",
3 "version": "1.0.0",
4 "scripts": {
5 "test": "node index.js"
6 }
7}
And workspace.json
gets updated to:
1{
2 "version": 2,
3 "projects": {
4 "simple": {
5 "root": "packages/simple"
6 }
7 }
8}
With this you can invoke any script defined in simple/package.json
via Nx. For instance, you can invoke the test
script by running yarn nx test simple
. And if you invoke this command a second time, the results are retrieved from
cache.
In this example, we used a generator to create the package, but you could also have created it by hand or have copied it from another project.
The change in workspace.json
is the only thing required to make Nx aware of the simple
package. As long as you
include the project into workspace.json
, Nx will include that project source into its graph computation and source
code analysis. It will, for instance, analyze the project's source code, and it will know when it can reuse the
computation from the cache and when it has to recompute it from scratch.
Creating Second NPM Package and Enabling Yarn Workspaces
Running nx g npm-package complex
results in:
packages/
simple/
index.js
package.json
complex/
index.js
package.json
nx.json
workspace.json
tsconfig.base.json
package.json
Now let's modify packages/complex/index.js
to include require('@myorg/simple')
. If you run yarn nx test complex
,
you will see an error saying that @myorg/simple
cannot be resolved.
This is expected. Nx analyzes your source to enable computation caching, it knows what projects are affected by your PR, but it does not change how your npm scripts run. Whatever tools you use in your npm scripts will run exactly as they would without Nx. Nx Core doesn't replace your tools and doesn't change how they work.
To make it work add a dependency from complex
to simple
in package.json
:
1{
2 "name": "@myorg/complex",
3 "version": "1.0.0",
4 "scripts": {
5 "test": "node index.js"
6 },
7 "dependencies": {
8 "@myorg/simple": "*"
9 }
10}
Then add the following to the root package.json
(which enables Yarn Workspaces).
1{
2 "workspaces": ["packages/*"]
3}
Finally, run yarn
.
yarn nx test complex
works now.
Non-JS Projects
In this example both projects use JavaScript, but we could have created, say, a Rust project instead. The only thing we would have to do is to manually define targets.
This is an example of manually defining a target (read more about it):
1{
2 "version": 2,
3 "projects": {
4 "simple": {
5 "root": "packages/simple",
6 "targets": {
7 "test": {
8 "executor": "@nrwl/workspace:run-commands",
9 "options": {
10 "command": "npm run test"
11 }
12 }
13 }
14 }
15 }
16}
Using Yarn/PNPM/Lerna
The example uses Yarn to connect the two packages. Most of the time, however, there are better ways to do it. The React,
Node, Angular plugins for Nx allow different projects in your workspace to import each other without having to maintain
cumbersome package.json
files. Instead, they use Webpack, Rollup and Jest plugins to enable this use case in a more
elegant way. Read about the relationship between Nx and Yarn/Lerna/PNPM.
What Nx Core Provides
Nx Understands How Your Workspace is Structured
If you run yarn nx dep-graph
you will see that complex
has a dependency on simple
. Any change to simple
will
invalidate the computation cache for complex
, but changes to complex
won't invalidate the cache for simple
.
In contrast to more basic monorepo tools, Nx doesn't just analyze package.json
files. It does much more. Nx also knows
that adding a require()
creates a dependency and that some dependencies cannot even be expressed in the source code.
Nx Orchestrates Tasks
Running yarn nx run-many --target=test --all --parallel
will test all projects in parallel.
Running yarn nx run-many --target=build --projects=app1,app2 --parallel
will build proj1
and proj2
and their
dependencies in parallel. Note that if app1
depends on the output of its dependency (e.g., shared-components
), Nx
will build shared-components
first and only then will build the app.
Nx Know What is Affected
Running yarn nx affected --target=test
will test all the projects affected by the current PR.
Nx Caches and Distributes Tasks
Running yarn nx build app1
will cache the file artifacts and the terminal output, so if you run it again the command
will execute instantly because the results will be retrieved from cache. If you use Nx Cloud
the cache will be shared
between you, your teammates, and the CI agents. Nx can also distribute tasks across multiple machines while preserving
the developer experience of running it on a single machine.
This works because Nx's computation caching and distributed task execution work on the process level. It doesn't matter
what build
means. It can be an npm script, a custom Nx executor, a Gradle task. Nx will handle it in the same way.
Adding Plugins
As you can see, the core of Nx is generic, simple, and unobtrusive. Nx Plugins are completely optional, but they can really level up your developer experience. Watch this video to see the plugins in actions.