Development with Nx

Create an NX workspace for a new project using myorg as the workspace name. The workspace name will be used as a prefix when creating libraries later such as @myorg/mylib.

np create-nx-workspace myorg

You will be asked a couple of questions such as choosing a preset (React, Next, react-express, angular, empty and more) and a CLI.

Alternatively you can specify a preset directly with

npx create-nx-workspace --preset=react

It creates a bunch of folders including apps and libs. Apps will contain all code that can be build and deployed. Libs contains libraries that can be used in apps. Libs is where most of the code will be stored.

There is only one package.json in the root folder.

workspace.json contains info about your projects and where they will be build and much more.

nx.json contains config of the nx workspace. You can define tasks here (more about that later).

NX Plugins

yarn nx list shows installed plugins, and those that are available to install, including community plugins.

Install any of those packages, e.g yarn add @nrwl/react.

Then run yarn nx list @nrwl/react to see all the possibilities this plugin offers.

Generating apps and libs with Nx CLI

There many different kinds of applications you can create, such as React, Angular, Express, Node etc. Nx is lets you add those via plugins that you either use indirectly via a preset (as shown above when creating a workspace) or you have to install a plugin first.

Another thing that comes to mind is what the difference between an Nx application and Nx library actually is. Usually applications should import most of the code from libraries. Read more about whether you should make a library or not on the official Nx page.

The following will create a React application in apps/myapp and also apps/myapp-e2e:

yarn add @nrwl/react

nx generate @nrwl/react:app myapp

Behind the scenes nx.json and workspace.json will be updated to add myapp and myapp-e2e as projects. Also additional files for babel and jest config are created.

The following will create a library mylib in libs/mylib:

nx generate @nrwl/react:lib mylib

You can additionally specify --directory mydir to create the library as libs/mydir/mylib. The project is the combination of the folder path, so in this example you can refer to this as a project with the name mydir-mylib.

All project and where they are pointing to are defined in workspace.json.

All libs will automatically get a path like @myorg/mylib specified in tsconfig.base.json, which lets you import files like import { Something } from "@myorg/mylib".

If you want to create a react component of header in this project you type:

yarn nx g @nrwl/react:component header --project=mydir-mylib

If you want to configure storybook for this lib run

nx generate @nrwl/react:storybook-configuration mylib

You can display --help for each command and have a --dry run:

yarn nx g @nrwl/react:application --help
yarn nx g @nrwl/react:application myapp --dry-run

Running commands

yarn nx run myapp:serve
yarn nx run myapp:lint
yarn nx run myapp:test

What commands are available? Have a look in /apps/myapp/project.json to see all available commands or modify them there. For example you can change the storybook.options.port there.

Running command parallely

We can call the serve command (aka target) for more than just one app/project and have them run paralelly:

yarn nx run-many --target=serve --projects=my-api,my-app --parallel=true

Creating custom commands

You can create a custom commands, for example one that cares of serving the app and api together. Edit a project.json of one of your libs or apps:

"targets": {
//...
    "serveCraAndStorybook" : {
      "builder" : "@nrwl/workspace:run-commands",
      "options": {
        "commands" : [
          {
            "command": "nx run ui:storybook"
          },
          {
            "command": "nx run pr-cra:serve"
          }
        ]
      }
    },
//...
}

Creating pure TypeScript lib

yarn nx g @nrwl/workspace:lib my-ts-lib

Creating an express app

yarn add @nrwl/express 
yarn nx g @nrwl/express:application my-api --frontendProject=my-project
yarn nx run my-api:serve

--frontendProject conveniently takes care of creating a proxy.conf.json in my-project to forward any request to /api to the backend server.

Visualize dependencies between apps and libs

yarn nx dep-graph

Running Nx Jest in Jetbrains IDE

Here is how you have to configure Jetbrains IDE to make Jest work within a NX workspace. When I say “work” I mean to make it possible that Jetbrains UI is used to visually indicate failed and succeeded tests instead of a console.

NX module import in Jetbrains IDE

One thing that annoyed me was that Jetbrains auto-imports TypeScript modules like this by default:

import { Something } from "@myorg/mylib".

This is kind of bad and it will even throw a warning such as this one:

ESLint: Projects should use relative imports to import from other files within the same project. Use "./path/to/file" instead of import from "@myorg/mylib"(@nrwl/nx/enforce-module-boundaries)

Luckily there is a setting that lets you change the default auto-import behavior. Navigate to Editor > Code Style > TypeScript and set “Use path mapping from tsconfig.json” to “Only in files outside specified paths“, now the IDE will use relative imports when you are inside a package and scoped-imports otherwise. Neat!

About Author

Mathias Bothe Contact me

I am Mathias, born 38 years ago in Heidelberg, Germany. Today I am living in Munich and Stockholm. I am a passionate IT freelancer with more than 14 years experience in programming, especially in developing web based applications for companies that range from small startups to the big players out there. I am founder of bosy.com, creator of the security service platform BosyProtect© and initiator of several other software projects.