> For the complete documentation index, see [llms.txt](https://tutorial.specian.co.uk/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tutorial.specian.co.uk/project-setup/lerna.md).

# Lerna

### Setup the project with one command

When I first had a look at [Lerna](https://github.com/lerna/lerna), I couldn't understand how it works and what was its value. Essentially, what would have been a repository is now a folder in `packages`. All the dependencies will be installed with `lerna bootstrap`.

What does this mean? When you clone the monorepo, you will get all the code required to run the app. When you run `yarn install` you'll install all the dependencies.

### Setting up Lerna

Create `lerna.json`

{% code title="lerna.json" %}

```javascript
{
  "packages": ["packages/**"],
  "version": "independent",
  "npmClient": "yarn"
}
```

{% endcode %}

Install Lerna **at the root of the project**.

```
$ yarn add lerna
```

### Let's try

Go to the `packages/api` and install `express`

```
$ cd packages/api
$ yarn add express
```

The `express` dependency should have been added to `packages/api/package.json`

{% code title="packages/api/package.json" %}

```javascript
  "dependencies": {
    "express": "^4.17.1"
  }
```

{% endcode %}

Let's do the same for `packages/web` and add `react`

```
$ cd packages/web
$ yarn add react
```

We should now have `node_modules` folders in `api` and `web`.

```
$ ls packages/api/node_modules # You should see express
$ ls packages/web/node_modules # You should see react
```

Let's try to delete both `node_modules` folders and bootstrap from the project's root directory. It should install all dependencies.

```
$ lerna bootstrap
```

{% hint style="info" %}
Don't forget to add `node_modules` to `.gitignore`.
{% endhint %}

### Post install

We can add anything in `scripts` of our `package.json` and run it with `yarn name-of-script`.

Let's try this first with our `package.json` from the root directory, :

{% code title="package.json" %}

```javascript
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "name-of-script": "echo my script"
},
```

{% endcode %}

```
$ yarn name-of-script
yarn run v1.15.2
$ echo my script
my script
✨  Done in 0.06s.
```

There are pre-defined keywords for `npm-scripts`. You can find all of them [here](https://docs.npmjs.com/misc/scripts) but we are interested in `postinstall`.

```
postinstall: Run AFTER the package is installed
```

We can add our bootstrap step here:

{% code title="package.json" %}

```javascript
"scripts": {
    "postinstall": "lerna bootstrap"
},
```

{% endcode %}

We can now install all the dependencies from the root directory:

```
$ yarn
[1/4] 🔍  Resolving packages...
$ lerna bootstrap
lerna notice cli v3.16.4
lerna info versioning independent
lerna info Bootstrapping 2 packages
lerna info Installing external dependencies
lerna info Symlinking packages and binaries
lerna success Bootstrapped 2 packages
✨  Done in 1.75s.
```

### Final files and folders structure

```
.
├── lerna.json
├── node_modules
├── package.json
├── packages
│   ├── api
│   │   ├── package.json
│   │   ├── node_modules
│   │   └── yarn.lock
│   └── web
│       ├── package.json
│       ├── node_modules
│       └── yarn.lock
└── yarn.lock
```

{% hint style="info" %}
[`lerna`](https://github.com/florianherrengt/book-code/tree/lerna) branch available on GitHub.
{% endhint %}
