Blog post #003
Duncan Faulkner – January 2020
What is an NX workspace and what are the benefits of using one?
This blog post takes a look at what an NX Workspace is, how to set one up and to discuss some of the benefits.
An NX Workspace is a product from nrwl.io that extends the Angulars CLI (Command Line Interface) and creates an application project structure for a variety of frameworks and libraries, not just Angular. The structure is based around a monorepo layout and is a technique that large enterprise organisations are adopting. The idea behind the monorepo is that every project or library are all contained in one large project (separated into individual projects under a parent folder).
Wait…all projects in the same solution? That can’t be best practice?
At first this sounds a little odd, why would you bundle all of your projects into one large repo? Surely that must be harder to find things, what about versioning of projects, how do you build individual projects? Can you build individual projects? Do you have to build all of them, what if they are independent projects? These are some the questions I asked when I first started to use the NX Workspace and I will try and answer these here.
Lets run through setting up an empty NX Workspace and we’ll add an Angular project later on. Open a terminal window and type:
npx create-nx-workspace@latest myproject cd myproject
This will create a new NX Workspace, after a few seconds it will ask for a type of project to create. At the moment these are:
# sample one What to create in the new workspace (Use arrow keys) empty [an empty workspace] web components [a workspace with a single app built using web components] angular [a workspace with a single Angular application] angular-nest [a workspace with a full stack application (Angular + Nest)] react [a workspace with a single React application] react-express [a workspace with a full stack application (React + Express)] next.js [a workspace with a single Next.js application]
For now, using the arrow keys select the `empty` project. The next step, is to select which CLI to use, choose NX.
Note: The NX Workspace is not a replacement for the Angular CLI, it extends the CLI by way of schematics and builders. This allows you to do more things, add different project types for example, an Angular front end with a Nest JS back end or a Node and Express application or React and Express and also the ability to build your own, but all contained in a monorepo structure.
After a few minutes a new empty project is created. Using your favourite text editor open the project. I’m using VS Code, so in the terminal cd into the myproject folder and type code-insiders . (don’t forget the dot!).
An empty NX workspace in VS Code.
What’s in the project?
The .vscode folder contains all the VS Code setting files. The apps folder is where all the projects like Angular, React live. The libs folder is where all the library projects live. And the tools folder is where all the pre/post scripts and schemas live. The rest of the files are just config type files.
The main difference between an NX Workspace and an Angular CLI project is the addition of the apps folder. This is the root folder where all projects (except for libraries) live. It’s also worth noting here that in an NX Workspace project there is only one package.json file for the whole solution.
At the moment what we just created doesn’t do anything, we need to add a application to this empty workspace (Angular/React/Vue for example). In the following example I will be setting up and Angular project.
From the terminal type:
npm install --save-dev @nrwl/angular
This will setup the NX Workspace so we can install the Angular project in this instance, there are other options. Because we setup the Workspace using NX CLI we have to use nx commands rather than ng commands, if you selected Angular CLI or are upgrading an existing Angular project to an NX Workspace then you can use the ng commands.
Next from the terminal type nx g @nrwl/angular:app myapp this will create our Angular project my-app and a myapp-e2e project, it will also set the projects to use Jest and Cypress both of these are testing suites (Jest for unit and Cypress for end to end testing).
Now we should be able to build and run the project, though at the moment there is just a home page with references to NX and the nrwl.io website. Both projects should build and run (including the myapp-e2e application, though this will need to be started separately).
At this point we can now start to build our application and we are not limited to one type of project either. We could have also created an React app and an Express/Node API application and have them all working together if our project called for it.
If our applications have common components that need to be shared, we can (and should) create a library project for this component. The advantages of using a library project keeps the main application as small as possible and allows us to reuse the same component time and time again across all project types, all we need is to include a reference to the library from our projects.
I should just point out that libraries were introduced as part of Angular (I think in version 6) and not NX Workspaces, the NX workspace creates a library folder by default.
So that’s the basic workspace created and with a simple Angular application. Back to the questions I raised at the beginning:
- Surely that must be harder to find things?
- What about versioning of projects?
- How do you build individual projects?
Surely that must be harder to find things.
At first this might seem to be harder, but in a short space of time it’s quite easy to navigate around, each application is in it’s own folder, and you could create parent folders for both application and the end to end project. Which would make it less cluttered under the apps folder.
Create library projects for code reuse, for components that are common and potentially common across multiple applications, for example login screens, user creation, role and permission assignments, menus these make for excellent library components.
What about versioning of projects.
Because all the applications reside under one repository they all have the same version number. This may not be ideal, for example what if you add a new application to an existing NX Workspace that has had previous production releases then the new application will start at that version?
I guess this does work to some extent, but I need to investigate this further there are still some questions that I feel need further clarification on and I’m collating some of these and I will update this post when I have something to add.
How do you build individual projects?
Is it possible to build individual projects – simple answer is yes you can. Make sure you have the NX CLI installed globally.
npm install -g @nrwl/cli
Then to build a specific application run:
nx run myapp:build
Your application should build and it should appear under the dist directory. In this directory you will see a *-es2015.js and *-es5.js you need to deploy both sets to your web server, when a client connects using an es2015 compatible browser the *-es2015.js files will be used, likewise if an older browser is used then the *-es5.js are used.
The NX Workspace is a great addition to the Angular CLI, I haven’t used all that it has to offer as there is a lot to it, but what I have used is excellent. It deals with the basic structure of an application and it feels natural when you get used to it’s layout of the project.
Note: If you create a empty NX Workspace and then add an Angular project, you might be wondering why there is no angular.json file, it is there but it’s called workspace.json.