How to create a monorepository with multiple services using Lerna and Yarn?

For developers, building scalable and maintainable applications can be a significant challenge, especially when working with large codebases and multiple services. Fortunately, using a mono-repository approach, combined with powerful tools like NX, Lerna, and Yarn, can provide a simplified development process that increases code commonality and reusability.

This detailed guide aims to help developers set up a monorepository using NX, Lerna, and Yarn. The guide includes detailed information on initial setup, directory structure, dependency management, testing, and deployment.

After mastering the tutorial, the developer will have a complete understanding of how to create scalable and maintainable applications using the mono-repository approach. He will also gain knowledge about the necessary tools and knowledge to move to a new level of development. Let’s get started!

Requirements

  • Lerna and Yarn for monorepository management

  • NX for version control of monorepositories

  • NestJS as an API service that serves administration requests under the API endpoint prefix /admin

  • Angular application for administrative frontend of NestJS service management

  • Setting up a monorepository

  • Plastic bag common will contain code that can be used by any application, such as interfaces, enums, etc.

  • Plastic bag common-be intended for shared libraries used exclusively by the API service

  • Plastic bag common-fe should only contain common libraries of the Angular frontend

  • Dockerizing an application with docker-compose.yml and Dockerfile

Git repository

All files for this tutorial can be find here.

Prerequisites

Yarn

Install Yarn and check the version.
From now on, we will be using Yarn for package management.

~$ npm install -g yarn**
~$ yarn --version**

Lerna

Install Lerna globally and check the version.

~$ yarn global add lerna
~$ lerna -v

NestJS CLI

Add NestJS CLI to global dependencies and check the version.

~$ yarn global add @nestjs/cli
~$ nest -v

Angular CLI

Install Angular CLI as a global package and check the version.

~$ yarn global add @angular/cli
~$ ng --version

Part 1: Setting up the monorepository and directory structure

What should be done:

  1. Initialize monorepository

  2. Initialize services as Yarn workspaces

  3. Add NestJS Application

  4. Add Angular Application

Road map

Do the following to create and run a multi-service monorepository using Lerna and Yarn.

Mono Repository Initialization

Create a new empty directory for your monorepository, in my case this is lehcode.

~$ mkdir [your-repo-name] && cd [your-repo-name]

The following command initializes the directory as Yarn workspace

~/lehcode$ yarn init
yarn init v1.22.19
success Saved package.json

Add Lerna to devDependency

~/lehcode$ yarn add -D lerna

Initialize Lerna by running the following command; it will create a config file lerna.json and a package directory at the root of the monorepository. Check out documentation for Lerna.

~/lehcode$ npx lerna init

Initializing Services as Yarn Workspaces

~/lehcode$ mkdir packages/{api,admin,shared,common-be,common-fe}

This command creates a new directory structure in the directory packages monorepository with five subdirectories: api, admin for applications; as well as shared, common-be, common-fe for shared libraries. These directories will be used for source code and configuration files for the API service, admin interface, and various shared libraries, respectively. At this point, the folder structure should look something like this:

.
├── lerna.json
├── node_modules
├── package.json
├── packages
│   ├── admin
│   │   ├── node_modules
│   │   └── package.json
│   ├── api
│   │   ├── node_modules
│   │   └── package.json
│   ├── shared
│   │   └── package.json
│   ├── common-be
│   │   └── package.json
│   └── common-fe
│   │   └── package.json
└── yarn.lock

Add NestJS App to Mono Repository

The following steps will explain how to add a NestJS application to our existing monorepository as a Yarn workspace.
Create a new NestJS application by running the command:

~/lehcode$ nest new [--dry-run] --directory packages/api/ -p yarn --strict

This command creates a new NestJS application and sets up Yarn as the package manager in the directory packages/api. Flag ‑-strict enables strict mode for the TypeScript compiler.
Try adding a flag --dry-run or -d on first run to simulate building a NestJS application without making any real changes to the file system.

Install the package @nrwl/nest to the root workspace by running the command

~/lehcode$ yarn add -D @nrwl/nest
~/lehcode$ cd packages/api/

Set up a NestJS API service to serve admin requests at the entry point /adminclient requests at the entry point /client. This can be done by changing the routing configuration in the app.module.ts file.
Return to the root directory of the monorepository.

~/lehcode/packages/api$ cd ../../

Add Angular App to Mono Repository

Initializing an external Angular application to administer the backend.

~/lehcode$ ng new --create-application --directory=packages/admin --new-project-root=./ --package-manager=yarn --style=scss
? What name would you like to use for the new workspace and initial project? admin
? Would you like to add Angular routing? Yes

You can add a flag --dry-run on first run to simulate building an Angular app without applying actual changes.

Change to the package folder:

~/lehcode$ cd packages/admin/

Manually run yarn dev once to respond to a data exchange request. Otherwise, the container will hang during assembly.
Return to the root of the repository:

~/lehcode/packages/admin$ cd ../../

Final Steps

Update the file package.json in the directory of each service (in ./packages/) so that the name field is in the format “<myorg>/<service-name>". This ensures that each service will have a unique package name that can be used to manage it with Yarn.

Install required packages @nrwlby running the following command

~/lehcode$ yarn add -D @nrwl/workspace @nrwl/nest @nrwl/angular

Shared Libraries

Add the shared libraries for the API by running the command

~/lehcode$ nx g @nrwl/workspace:lib common-be

Add any required code to the library common-be and configure the API service to use the library by importing it into the app.module.ts file.

Add shared libraries for the admin interface by running the command

~/lehcode$ nx g @nrwl/workspace:lib common-fe

Add any required code to the library common-fe and configure the admin interface to use the library by importing it into the appropriate files.

Part 2: Set up and Version Control Git in a Mono Repository with NX

Configuration

NX provides a convenient way to set up Git versioning in a monorepo, allowing you to easily manage version tags. With the command nx version you can set up versioning for each package in your monorepository, and NX will automatically generate and update version tags in Git when changes are made to packages.

This feature is especially useful when you have multiple packages in your monorepository that depend on each other. With Git versioning, you can easily track changes and dependencies between packages and ensure that the correct versions are being used.

Team nx version used to set up Git version control in an NX-managed monorepository. This part will show you how to create and update version tags in Git for packages in your monorepo.

Follow these steps to set up Git versioning for your monorepo using NX. NX will automatically update version numbers in files package.json and generate Git tags for each of the new versions.

  1. Make sure you have initialized Git in your monorepo by running the command in the root directory. Run command $ git init in the root directory of the monorepository.

  2. Run command $ nx version in the root directory of the monorepository. This will open an interactive prompt that will guide you through the version control process.

    1. Choose whether to promote all packages in the monorepository or only a specific package.

    2. Select the version to update (major, minor or patch).

    3. Choose if you want to create a Git tag for the new version.

    4. You will be prompted to preview the changes that will be made to the files package.json and Git history.

    5. Confirm version changes. Press Enter.

Use command $ nx affected if you need to determine the impact of changes in a monorepository on other packages and services.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *