Codementor Events

Creating a full-stack Nx monorepo

Published Jan 19, 2019

First of all, why a monorepo? there are many articles out there that explain why this kind of setup facilitates the development of complex applications. Code reusability and consistency are hugely improved, making visible any particular change on the system across all the dependencies, and facilitating the integration tests.

@nrwl/nx is a tool built on the top of @angular/cli that help us to create a workspace. with special folders for applications and libraries, along with some scaffolding to help with building, linting, and testing, encouraging the global usage of best practices and team standards.

Setting up an Nx monorepo

Nx can be installed in the following ways:

npm install -g @angular/cli @nrwl/schematics
yarn add global @angular/cli @nrwl/schematics

Within @nrwl/schematics we have the utility to create our workspace:

create-nx-workspace mymonoreponame

This will create an Nx Workspace using Angular CLI with the Nx schematics collection. You can also add Nx capabilities to an existing CLI project using:

ng add @nrwl/schematics

Within the workspace, we will have the apps, libs, tools, with the configuration files for Angular, Nx, TSLint and Typescript:

/apps           <- our frontend and backend apps
/libs           <- shared libraries
/tools          <- schematic and misc tooling
angular.json    <- angular configuration for apps and libs
nx.json         <- nx metadata
package.json    <- main project info and scripts
tsconfig.json   <- global compilation config
tslint.json     <- global lint rules

By default, Angular uses Karma and Protractor for testing, but Nx supports the usage of Jest and Cypress. If you want to enable Jest, you need to execute:

ng generate jest

this will install the packages and update the required configurations, and we need to do it only once per workspace.

Creating a Frontend App

Adding new apps to an Nx workspace is done by using the Angular CLI generate command, with the app schematic provided by Nx:

ng generate app myfrontendappng generate app web --unitTestRunner=jest --e2eTestRunner=cypress

This will add the required folders and files, and its configuration like:

/apps
  /web
    /src             <- Angular app
    browserslist     <- supported browsers criteria
    jest.config.js   <- Jest config
    tsconfig*.json   <- custom compilation rules
    tslint.json      <- custom lint rules
  /web-e2e
    /src             <- Angular e2e tests
    cypress.json     <- Cypress config
    tsconfig*.json   <- custom compilation rules

Creating a Backend App

We need to use the node-app schematic here, and optionally we can pick a backend framework like express or nestjs.

ng generate node-app server
ng generate node-app server --framework=nestjs

generating a backend App with a pretty similar structure:

/apps
  /server
    /src             <- NestJS/Express App
    jest.config.js   <- Jest config
    tsconfig*.json   <- custom compilation rules
    tslint.json      <- custom lint rules

as you can see, Nx provides easy ways to customize the global rules when a specific project requires it and organizes our apps in a consistent way.

Creating Libraries

Now it’s time to share some code using libs. Let’s create theshared one:

ng generate lib mylibraryname
ng generate lib shared --unitTestRunner=jest --publishable

this will create a consistent structure but this time with some new files:

/libs
  /shared
    /src
      /lib             <- library source
      index.ts         <- library entrypoint
    jest.config.js     <- test runner config
    ng-package.json    <- packaging configuration
    package.json       <- library npm metadata
    tsconfig*.json     <- custom compilation rules
    tslint.json        <- custom lint rules

the --publishable option added some package files required to publish the built library on an npm registry. That’s helpful if another repository or project will use this library outside of the monorepo.

This library generation will also configure the global tsconfig.json paths with the library entry point. Be sure to customize your project scope in the nx.json file or while you create your workspace:

From there, you can add some common components and utilities inside the @myproject/shared library, and import them in your apps easily. You can think about how many libraries do you want to handle to modularize your project properly, and Nx will take care of the setup for you.

Nx Utilities

Nx also knows how your apps and libs depend on each other. To see the dependency graph of your project just run:

npm run dep-graph
yarn dep-graph

also, Nx provides a useful script for CI to test only the changed code on a branch. If you modify a library, it will run tests for all the apps that use it:

npm run affected:test --base=master
yarn affected:test --base=master

and finally, you can keep your Nx up to date running the following script when a new release comes out:

yarn add @nrwl/schematics@latest
yarn update

you can check all the available scripts inside the package.json file.

Angular Console

Recently the Nrwl.io team released a powerful tool that gives a visual overview of the complete project and the available schematics to use. With it you can check deeper all the options that you have while creating Apps and Libraries, and also generating components, services, etc. You can learn more at angularconsole.com.

NgRx Schematics

Using it, I’ve been developing a custom set of scripts with the available schematics to build my Stores, Reducers, Actions, and Effects faster. Here I share some of them with my custom approach to structure them.

Root Store with Actions and Effects

Tools shouldn’t limit your taste when it comes to structure your projects, so playing with the Angular Console, I’ve been finding the right commands to use to keep my standards and have a result like:

/app
  /store
    /actions
      session.actions.ts
    effects.ts
    index.ts
    reducers.ts
    state.ts

and I made it with three actions on the Console that resulted in the following commands:

ng generate @ngrx/schematics:store app --statePath=store --no-flat --no-spec --root --module=app.module.ts --stateInterface=AppState

ng generate @ngrx/schematics:effect store/router --no-flat --no-spec --root --module=app.module.ts

ng generate @ngrx/schematics:action store/lang --group

you can check the detailed commits and my customizations (and more) here.

Enjoy!

Angular is moving on with awesome tools and patterns that will make our life as developers pretty enjoyable, so keep it up with the new releases!

Discover and read more posts from Mateo Tibaquirá Palacios
get started
post commentsBe the first to share your opinion
Show more replies