Fullstack Angular 13: Monorepo with lerna & express.js

Fullstack Angular 13: Monorepo with lerna & express.js

Throughout this tutorial, we'll be building a full stack monorepo project with Lerna, Angular 13, Node.js and Express.js.

We'll use a monorepo architecture to set up our project, which essentially means that we'll use a single repository to handle both client and server applications (as well as any shared libraries) rather than dealing with several repositories. We'll be doing this using an utility called lerna along with npm workspaces.

We’ll be using both npm workspaces and lerna to work with our project’s codebase.

Prerequisites

Before starting, make sure you have Node.js along with npm 7+ installed on your local development machine. Workspaces are only supported starting with npm version 7.

Let's get ready to have fun.

Open a new command-line interface and begin by installing lerna globally on your development machine using the following command:

npm install --global lerna

Following this step, create a directory for your project and initialize lerna as follows:

mkdir angularnodelernademo
cd angularnodelernademo
lerna init

If successfully executed, the previous command should output the following on the screen:

lerna notice cli v4.0.0
lerna info Initializing Git repository
lerna info Creating package.json
lerna info Creating lerna.json
lerna info Creating packages directory
lerna success Initialized Lerna files

We created the basic architecture of our monorepo project.

The configuration for lerna is stored in the lerna.json file, whereas the settings for the whole (client and server) project is stored in the package.json file. The frontend and backend applications, as well as any libraries you want to use across the two apps, should be located under the packages/ subdirectory. The script will also execute the git init command, which will be used to set up a Git repository. The various configuration options for lerna may be found at https://github.com/lerna/lerna#lernajson.

If you run the ls command on your current project’s folder, you’ll see the following folder structure and files:

lerna.json package.json packages

Lerna has initialized an empty Git repository, but it’s also a good practice to create a .gitignore file, so simply run the touch .gitignore command at the root of the project and add the following lines:

node_modules
.DS_Store

You can make sure you have a Git repository by running the following command:

git status

This command should have a similar output:

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    lerna.json
    package.json

Next, we need to set the version for the entire monorepo project. Simply open the lerna.json file and set and set version to "1.0.0” as follows:

{
  "packages": [
    "packages/*"
  ],
  "version": "1.0.0"
}

It’s also a good practice to set the version in the project’s level package.json file as follows:

{
  "name": "root",
  "private": true,
  "devDependencies": {
    "lerna": "^4.0.0"
  },
  "version": "1.0.0"
}

You can find more details on lerna via the official website at https://lerna.js.org/.

Setting up our Node.js server

In this part, we'll proceed to set up our server project and install Express.js, which will allow us to rapidly launch a server without having to contend with the low-level APIs exposed by the Node.js technology.

The npm command enables developers to build a project (an empty folder with a package.json file). Let's look at how to utilize it to create a package.json file.

Let’s start by adding a new backend/ folder inside the monorepo’s packages/ folder.

Head over to your terminal and run the following commands:

cd packages
mkdir backend && cd backend

Please keep in mind that the folder's name is entirely up to you; you may call it anything you choose.

Since, we’ve, navigated inside the backend/ folder, simply run the following command to generate a package.json file for the backend application:

npm init --yes

The --yes option instructs npm to generate a package.json file with the default settings, which are in our case:

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Now that we’ve created a node project for the backend application, we can install dependencies that are only required by the server such as express.js since it will be needed to start a server.

Head back to your terminal and run the following command from the packages/backend/ folder which we’ve already navigated into it:

npm install express  

At the time of this writing express v4.17.3 is installed and added to the dependencies object of the server’s package.json file:

"dependencies": {
    "express": "^4.17.3"
  }

We’ll see later how to install additional dependencies which will be either required by both the backend and frontend apps and therefor will be installed at the project’s level or only required by one of them and will be installed at the package’s level.

For now, let’s proceed to install Angular CLI 13 and create the frontend package that will be powered by Angular.