Managing Javascript Projects With Monorepo

Alperen Karlı
Testinium Tech
Published in
4 min readJun 14, 2021

When you decide to start a project, you should be concerned about its architecture. Even small projects should be suitable for growth without disturbing their structure. This may be difficult for you at first because nowadays people start to think of giving a printout as more important than the print itself. From here I’ll talk about the monorepos.

It will be more effective in terms of code sharing if we use small pieces that do the job instead of large code blocks. It is getting more difficult to control, update and change these structures in a large number of repositories. To overcome these problems and to make the installation process healthier, we use the multi-package repository method. It’s called monorepos. So, what’s monorepo?

A monorepo (mono repository) is a single repository that stores all of your code and assets for every project.

Pros:

  • Single lint, build, test and release process
  • Better organize all modules
  • Easier to get the project up and running
  • The testing process becomes more convenient

Cons:

  • Huge codebase
  • Excessively large repos

Now let’s come to how to create a monorepo with a javascript tool: Lerna.

Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.

Lerna can also reduce the time and space requirements for numerous copies of packages in development and build environments — normally a downside of dividing a project into many separate NPM packages.

It will be better if we go through an example to show you this process.

1- Let’s start by creating a folder and init Lerna

Codes in the code block represent creating a project folder and entering the created folder respectively.

npm install -g npx #install npx command runner globally
(or
npm install --global lerna) # and then remove "npx" from "lerna init" in below
mkdir monorepo-example && cd $_ #create the folder
npx lerna init --independent #init monorepo config

--independent flag means that each subrepo has its own npm versionning, without the independent flag all of the subrepos follow the same versionning.

Then this will create a lerna.json configuration file as well as a packages folder. It may take some time (get grab a coffee ☕). At last, your folder structure should now look like this:

monorepo-example/
├── packages/
├── package.json #package file
└── lerna.json #lerna configuration file

Your first monorepo is ready! Here we go 😎

2- Create the first package

Now we dive into our packages folder. I create two angular projects. One is including a library that I create for this example and another one for the project.

npm install --global @angular/cli

You must install the angular CLI if you haven’t installed it yet.

cd packages
ng new testinium-components --create-application=false
cd testinium-components
ng generate library testinium-components --prefix=testinium
ng generate component button --project=testinium-components

You can change “testinium-components” with your individual project name. After creating the button component we can add a simple text string to it.

button.component.ts
<button>{{ text }}</button> #button.component.html

In that way, we have created an angular library and added a button to it. If you want to use your button component you should add the line below to the public-api.ts.

export * from './lib/button/button.component';

And also don’t forget to add ButtonComponent to the library module’s exports.

At last, we build out our library. We are ready to import it into our project.

ng build testinium-component

4- Create the second package

Now let’s return to our packages folder. We create an empty angular project named “project”.

ng new projectnpx rimraf node_modules package-lock.json

You must call “npx rimraf” in both packages. After that command, we use Lerna's bootstrap command. It installs all of their dependencies and links any cross-dependencies.

cd ..
npm install && npx lerna bootstrap

Then we link the components to the project and use them as we want. Every change is binding so don’t hesitate to update your library and see changes!

npx lerna add testinium-components --scope=project

5- Final Structure

./
├── packages/
│ ├── project/
│ └── testinium-components
├── package.json
└── lerna.json

To see the output you must add the button to the app.component.html.

<testinium-button [text]=”’Example’”></testinium-button>

And of course, import the module to the app.module of the project.

imports: [
BrowserModule,
TestiniumComponentsModule
],

If you want more, you can set up the storybook in this project or in another repo to challenge yourself. This way, you can see your components and use them in the project accordingly.

6- Conclusion

It’s not easy to maintain a project without structure. We’ve come a long way since the beginning. So we:

  • Looked to monorepos and lerna
  • Created a monorepo that includes an angular library project and another project to show the link between them.
  • Have completed the angular library creation in a simple way.
  • Used different lerna commands.

I hope you enjoy while reading.

Until next time, farewell 👋

--

--