Setting up a monorepo with Lerna for a TypeScript project
Tags: lerna, node, typescript, npm
Published: 2019-07-08 17:30:38

---
title: Setting up a monorepo with Lerna for a TypeScript project
published: true
tags: lerna,nodejs,typescript,npm
canonical_url: https://blog.logrocket.com/setting-up-a-monorepo-with-lerna-for-a-typescript-project-b6a81fe8e4f8
---

![](https://cdn-images-1.medium.com/max/1024/1*BriahqbFqeAW9lXDzuUgzw.png)

It is often quite useful to use a single repository for maintaining an entire project with all of the packages in it. There is a rumor that Google and Facebook use a single repository for all of their projects. This solution can be quite handy when a company uses a similar technology and when projects share common dependencies and files.

Popular JS projects like Angular, React, Meteor, Babel, NestJS and many others are using a single repository for all of their packages. In fact, some of them use Lerna for it.

[**Lerna**](https://lernajs.io/) is a popular and widely used package written in JavaScript for setting and managing multi-package and multi-project single repository for Node.js projects with **NPM** and  **GIT**.

Lerna has two modes: fixed and independent.

Fixed mode keeps all versions of packages at the same level. This approach is quite popular these days. You may have seen it in Angular.

![](https://cdn-images-1.medium.com/max/515/1*Pg9JrNskIa60kQX_pLViYg.png)

Independent mode allows us to have different versions per package.

Maintaining all custom packages in a single repository sounds tempting and, as a matter of fact, it is quite easy with Lerna.

[![](https://cdn-images-1.medium.com/max/1024/1*GPjaPKNNUYHU8EsA3Z0JGA.png)](https://logrocket.com/signup/)

#### Installation

We will install Lerna as a global dependency:

```jsx
npm install -g lerna
```
#### Lerna & TypeScript

As **Lerna** is intended to work with **JavaScript** and not **TypeScript** , we will have to adjust the initial configuration for this project.

#### NPM

**Lerna** works with **NPM** which stands for Node Package Manager. You will need to create an account there: [www.npmjs.com](http://www.npmjs.com) and organization too, as we will create example with scoped packages: @organization/my-project

- [How to set up a new npm account & install npm | npm Documentation](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)

#### GIT

Our packages are going to be public, and for the sake of this project, we will create a **Github** repository.

### Let’s get our hands dirty

Let’s build a simple project which consists of multiple packages for our imaginary project called **hospital-sdk.**

![](https://cdn-images-1.medium.com/max/959/1*gwivSLxlisO2rMlteOuUOQ.png)

Create folder hospital and initialize Lerna inside the folder with:

```jsx
lerna init && npm install
```

This command will create lerna.json with a default folder structure in it.

- /packages
- lerna.json
- package.json

**/packages** is a placeholder for our shared packages  
**lerna.json** is a Lerna configuration file

```jsx
{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}
```

**Lerna** doesn’t create  **.gitignore** we will create one with this content:

.gitignore

```jsx
node_modules/
lerna-debug.log
npm-debug.log
packages/*/lib
.idea
```

We will use **TypeScript** in our project so we can treat it as a shared dependency. Which means we should add it on top level **package.json** with:

```jsx
npm install typescript @types/node — save-dev
```

This is a recommended approach, as we want to use the same tooling across our packages. Alongside **TypeScript** we will install type declarations for Node.js.

#### Preparing build script

As we mentioned before, **Lerna** is intended to be used with **Node.js** and not with **TypeScript**. We will need to add additional configuration to make that work with **TypeScript**.

As this is a demo project, we will assume that we will have a few modules: **patient**, **doctor**, and **scheduler**.

#### Creating packages

To create packages we are going to use the lerna create terminal command from the root of our project.

The lerna create doctor command will guide us through the creation of a new package. The name of the package is important. The name of this package is going to be: @hospital-sdk/doctor

![](https://cdn-images-1.medium.com/max/825/1*SMRKxkaJI8UNlhxHKhxcQA.png)

We will repeat the same process for packages **patient** and **scheduler**.

The result should be:

![](https://cdn-images-1.medium.com/max/501/1*z4nBnT172voORPe8CoDTXw.png)

As we are using **TypeScript** for all packages, we will have one common tsconfig.json defined in the root of our project. Our tsconfig.json will look like:

```jsx
{
 "compilerOptions": {
   "module": "commonjs",
   "declaration": true,
   "noImplicitAny": false,
   "removeComments": true,
   "noLib": false,
   "emitDecoratorMetadata": true,
   "experimentalDecorators": true,
   "target": "es6",
   "sourceMap": true,
   "lib": [
     "es6"
   ]
 },
 "exclude": [
   "node_modules",
   "**/*.spec.ts"
 ]
}
```

Each individual package will have its own tsconfig.json whose extended root, individual tsconfig.json will look like:

```jsx
{
 "extends": "../../tsconfig.json",
 "compilerOptions": {
   "outDir": "./lib"
 },
 "include": [
   "./src"
 ]
}
```

After we added tsconfig.json in each package, we will create an **src** folder inside each package with a **TypeScript** file for that package.

We also need to register **tsc** script in each individual **package.json.**

The result should be:

![](https://cdn-images-1.medium.com/max/1024/1*Z97AdHoeuw72NHdxOYwR9g.png)

We added simple logic in each .ts file.

We can test our setup by running:

```jsx
lerna run tsc
```

The command above will run the tsc script in all created packages:

![](https://cdn-images-1.medium.com/max/897/1*66nX59a4rOFHJ70hvra10A.png)

If all goes well, we will compile **TypeScript** files from the **src** folder into **lib** folder in each package.

If we take a look at package.json for any package in our project, we will see attributes like **directories** , **files, typings, publishConfig** and  **main:**

![](https://cdn-images-1.medium.com/max/501/1*Wfg3WmU_7QPtBg9wuCH0Fg.png)<figcaption>packages/doctor/package.json</figcaption>

These are very important to us as they control what will be pushed to **NPM** and what will be the entry point for our library ( **main** and **typings** attributes ).

#### GIT

We will create a Github repository for this project and push all of the code there.

#### Publishing

Our goal is to publish all packages under the same **NPM** scope ( organization ). **NPM** organization can be private as well; in that case you can control who is going to see/use your packages.

We created a public ( free ) organization at npmjs.org:

![](https://cdn-images-1.medium.com/max/1024/1*WqqLdTpsYPiieGScJ9WAUQ.png)

We have to log in to that organization from terminal:

![](https://cdn-images-1.medium.com/max/764/1*GLHj5SVAs6OBCbHbV44hFQ.png)

At this moment, we have organization and build script ready. Let’s glue it all together under one npm script from the root package.json:

```jsx
{
 "scripts": {
   "publish": "lerna run tsc && lerna publish"
 }
}
```

From terminal we will run:

```jsx
npm run publish
```

**Lerna** will guide us through the publishing process where we will need to choose a package version and push tags to Github.

If all goes well, we will see message at the end: _lerna success published 3 packages._

#### Verify installation

We will create folder integration in our project directory and install all packages in it:

```jsx
npm init --yes
npm install ts-node --save-dev
npm install @hospital-sdk/doctor --save
npm install @hospital-sdk/patient --save
npm install @hospital-sdk/scheduler --save
```

In **integration/src/index.ts** we can import all our packages and console.log it:

```jsx
import { Doctor } from "@hospital-sdk/doctor";
import { Patient } from "@hospital-sdk/patient";
import { Scheduler } from "@hospital-sdk/scheduler";

console.log(new Doctor());
console.log(new Scheduler());
console.log(new Patient());
```

Finally, we can add start script in **integration/package.json** :

```jsx
{
  "scripts": {
   "start": "ts-node src/index.ts" 
  }
}
```

and run it from terminal:

![](https://cdn-images-1.medium.com/max/732/1*fWb4hMqrzBmtVqW2XfVxBQ.png)

**Bingo!** We successfully called exported classes from our packages.

#### Lerna commands

There are a couple of Lerna commands worth mentioning:

`lerna add` Adds npm dependency to all or specific package within a project  
`lerna bootstrap` Install all dependency from all packages within a project

#### Links

Source code is published on:

[vladotesanovic/hospital-sdk](https://github.com/vladotesanovic/hospital-sdk)

[https://www.npmjs.com/package/@hospital-sdk/doctor](https://www.npmjs.com/package/@hospital-sdk/doctor)

[lerna/lerna](https://github.com/lerna/lerna)
* * *
### Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps

[![](https://cdn-images-1.medium.com/max/1024/1*s_rMyo6NbrAsP-XtvBaXFg.png)](https://logrocket.com/signup/)<figcaption><a href="https://logrocket.com/signup/">https://logrocket.com/signup/</a></figcaption>

[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

[Try it for free.](https://logrocket.com/signup/)
* * *
The post [Setting up a monorepo with Lerna for a TypeScript project](https://blog.logrocket.com/setting-up-a-monorepo-with-lerna-for-a-typescript-project-b6a81fe8e4f8/) appeared first on [LogRocket Blog](https://blog.logrocket.com).