# Using with Lerna

Turborepo and Lerna have a lot a in common, but also some key differences.

**tl;dr** you can use Lerna and Turbo together.

- Use `lerna` symlinking (`lerna bootstrap`) packages, publishing and changelog generation
- Use `turbo` for task running and caching

## Tool Comparison

Lerna is a a monorepo task runner and NPM workspace implementation. Both Turborepo and Lerna can be used to run tasks across packages in parallel and also topologically (i.e. if A depends on B, run B before A).

### Caching

However, unlike Turborepo, Lerna has no ability to [cache prior work](../features/caching) or [intelligently schedule tasks (i.e. create pipelines)](../features/pipelines).

### Task Scheduling

Turborepos's task scheduler is more powerful than Lerna's (which can only schedule one task at a time) thanks to [Turborepo pipelines](../features/pipelines). Turborepo reduces idle CPUs, saves compute resource, and collapse waterfalls—which ultimately results in faster overall builds.

Let's look at an example. Imagine you have two packages A and B each with 3 tasks `build`, `test`, and `bundle`, where A depends on B being built....

![Turborepo vs. Lerna Task Execution](/images/docs/turbo-vs-lerna-execution.png)

The above may not not look like much. But imagine that A's `build` task takes 20 minutes and now look at when B's tests run. Woah....yeah....scheduling can save insane amounts of time when you have long build times.

### Package Publishing, Versioning, and Changelog Generation

Lerna can version and publish packages to NPM registries as well as create changelogs. It's extremely good at this, especially for releasing canary pre-releases. While Turborepo may eventually tackle these features, at the time of writing, it is not a high priority goal (we suggest using using [atlassian/changesets](https://github.com/atlassian/changesets) in the meantime). If changesets isn't for you, and you want to stick with Lerna's publish flow, you can use Lerna and Turborepo together.

## Example migration

Say you have a Lerna-powered monorepo setup like so:

```json
// lerna.json
{
  "npmClient": "yarn",
  "packages": ["packages/*"],
  "command": {
    "version": {
      "exact": true
    },
    "publish": {
      "npmClient": "npm",
      "allowBranch": ["master", "canary"],
      "registry": "https://registry.npmjs.org/"
    }
  },
  "version": "2.1.6"
}
```

```json
{
  "private": true,
  "scripts": {
    "dev": "lerna run dev --stream --parallel",
    "test": "lerna run test",
    "build": "lerna run build",
    "prepublish": "lerna run prepublish",
    "publish-canary": "lerna version prerelease --preid canary --force-publish",
    "publish-stable": "lerna version --force-publish && release && node ./scripts/release-notes.js"
  },
  "devDependencies": {
    "lerna": "^3.19.0"
  }
}
```

To add turbo, run the following command in your terminal

```sh
yarn add turbo --dev -W
```

Alter `package.json` to use `turbo` for task running, but keep `lerna` for versioning.

```diff
{
  "private": true,
  "scripts": {
-   "dev": "lerna run dev --stream --parallel",
+   "dev": "turbo run dev --parallel --no-cache",
-   "test": "lerna run test",
+   "test": "turbo run test",
-   "build": "lerna run build",
+   "build": "turbo run build",
    "prepublish": "lerna run prepublish",
    "publish-canary": "lerna version prerelease --preid canary --force-publish",
    "publish-stable": "lerna version --force-publish && release && node ./scripts/release-notes.js"
  },
  "devDependencies": {
    "lerna": "^3.19.0",
+   "turbo": "*"
  },
+ "turbo": {
+   "pipeline": {
+     "build": {
+       "dependsOn": ["^build"]
+       "outputs": ["dist/**"]
+     },
+     "test": {
+       "outputs": []
+     },
+     "dev": {
+       "cache": false
+     }
+   }
  }
}
```

If you're not using yarn or NPM workspaces with Lerna, you should keep around your `lerna bootstrap` command if you have one. Turborepo considers Lerna a valid workspace implementation. Everything should work as expected.
