docs(nx-dev): update migration guide (#30052)
This commit is contained in:
parent
0006fbfc0b
commit
1257621031
@ -638,14 +638,6 @@
|
||||
"children": [],
|
||||
"disableCollapsible": false
|
||||
},
|
||||
{
|
||||
"name": "Nx and Turborepo",
|
||||
"path": "/concepts/turbo-and-nx",
|
||||
"id": "turbo-and-nx",
|
||||
"isExternal": false,
|
||||
"children": [],
|
||||
"disableCollapsible": false
|
||||
},
|
||||
{
|
||||
"name": "Buildable and Publishable Libraries",
|
||||
"path": "/concepts/buildable-and-publishable-libraries",
|
||||
@ -859,14 +851,6 @@
|
||||
"children": [],
|
||||
"disableCollapsible": false
|
||||
},
|
||||
{
|
||||
"name": "Nx and Turborepo",
|
||||
"path": "/concepts/turbo-and-nx",
|
||||
"id": "turbo-and-nx",
|
||||
"isExternal": false,
|
||||
"children": [],
|
||||
"disableCollapsible": false
|
||||
},
|
||||
{
|
||||
"name": "Buildable and Publishable Libraries",
|
||||
"path": "/concepts/buildable-and-publishable-libraries",
|
||||
|
||||
@ -875,17 +875,6 @@
|
||||
"path": "/concepts/typescript-project-linking",
|
||||
"tags": ["project-linking"]
|
||||
},
|
||||
{
|
||||
"id": "turbo-and-nx",
|
||||
"name": "Nx and Turborepo",
|
||||
"description": "",
|
||||
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
|
||||
"file": "shared/concepts/turbo-and-nx",
|
||||
"itemList": [],
|
||||
"isExternal": false,
|
||||
"path": "/concepts/turbo-and-nx",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"id": "buildable-and-publishable-libraries",
|
||||
"name": "Buildable and Publishable Libraries",
|
||||
@ -1179,17 +1168,6 @@
|
||||
"path": "/concepts/typescript-project-linking",
|
||||
"tags": ["project-linking"]
|
||||
},
|
||||
"/concepts/turbo-and-nx": {
|
||||
"id": "turbo-and-nx",
|
||||
"name": "Nx and Turborepo",
|
||||
"description": "",
|
||||
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
|
||||
"file": "shared/concepts/turbo-and-nx",
|
||||
"itemList": [],
|
||||
"isExternal": false,
|
||||
"path": "/concepts/turbo-and-nx",
|
||||
"tags": []
|
||||
},
|
||||
"/concepts/buildable-and-publishable-libraries": {
|
||||
"id": "buildable-and-publishable-libraries",
|
||||
"name": "Buildable and Publishable Libraries",
|
||||
|
||||
@ -260,12 +260,6 @@
|
||||
"tags": ["project-linking"],
|
||||
"file": "shared/concepts/typescript-project-linking"
|
||||
},
|
||||
{
|
||||
"name": "Nx and Turborepo",
|
||||
"id": "turbo-and-nx",
|
||||
"mediaImage": "./shared/concepts/nx-media-monorepo.jpg",
|
||||
"file": "shared/concepts/turbo-and-nx"
|
||||
},
|
||||
{
|
||||
"name": "Buildable and Publishable Libraries",
|
||||
"id": "buildable-and-publishable-libraries",
|
||||
|
||||
@ -1,177 +0,0 @@
|
||||
# Nx and Turborepo
|
||||
|
||||
Turborepo is a build tool that was released in December 2021. It borrows many ideas from Nx, so, naturally, some folks will compare Nx and Turborepo. This document provides some context to help you evaluate what works best for you.
|
||||
|
||||
{% callout type="warning" title="Few key differences" %}
|
||||
Note that the relationship between Nx and Turborepo isn’t the same as with Nx and say Yarn workspaces or Lerna. Nx and Yarn workspaces are complementary, so it makes sense to use both in some situations. Turborepo is a subset of Nx (at this point), so we don’t think it makes sense to use both.
|
||||
{% /callout %}
|
||||
|
||||
We do our best to be unbiased, but, of course you should do your own research. Read the docs, try things out and build your own opinion.
|
||||
|
||||
We clearly separate Nx (the open source tool) and [Nx Cloud](https://nx.app) (the SAAS product). Turborepo doesn’t have such a separation. Hence, in this guide we compare Turborepo with Nx+Nx Cloud (so it’s apples to apples).
|
||||
|
||||
We are going to compare the tools in three different ways: **features**, **tech and performance**, and **community**.
|
||||
|
||||
## Features
|
||||
|
||||
#### 1. Incremental Adoption
|
||||
|
||||
Both Turbo and Nx can be added to a repo with almost no friction. Install `turbo` and add a `turbo.json` or install `nx` and add an `nx.json`. In this initial setup, both tools enable task running and computation caching.
|
||||
|
||||
In addition, Nx allows you to incrementally enable [plugins and supporting features](#plugins-and-supporting-features) that are not available with Turborepo.
|
||||
|
||||
Here are some examples for Nx:
|
||||
|
||||
- [Article: Setup a Monorepo with PNPM and speed it up with Nx](/blog/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx)
|
||||
- [Video: Nx in 100 seconds: Adding Nx to an existing PNPM workspace](https://youtu.be/8X2sGZn_ffY)
|
||||
|
||||
#### 2. Understanding your workspace
|
||||
|
||||
The starting point of any non-trivial monorepo management tool is to be able to understand the monorepo workspace structure, what projects there are and how they relate to each other.
|
||||
|
||||
- Turborepo only analyzes package.json files to understand how projects relate to each other. Built-in Nx plugins also analyze package.json files but in addition they analyze JS/TS files, so you don't have to have bogus package.json files (that you don’t use for the purposes of installing packages or publishing) in your repo. There are plugins for Nx that do that for other languages (e.g., Golang, .Net).
|
||||
- Since the computation of the project graph can take a lot of time for complex workspaces, both Nx and Turborepo have a daemon process to create the graph in the background.
|
||||
- **Nx has [module boundary rules](/features/enforce-module-boundaries), which are essential for any monorepo with multiple teams contributing.** You can say that some things in the monorepo are private to your team so they cannot be depended on by other teams. Turborepo doesn't have project boundary rules. **Project boundary rules prevent the monorepo from becoming a “big ball of mud”.**
|
||||
|
||||
#### 3. Project graph visualization
|
||||
|
||||
Being able to visually explore a monorepo workspace can be a deal breaker when you need to debug and troubleshoot large monorepo workspaces.
|
||||
|
||||
- Nx has a rich, interactive visualiser (watch a video [here](https://www.youtube.com/watch?v=UTB5dOJF43o))
|
||||
- Turborepo has a basic graphviz image export.
|
||||
|
||||
#### 4. Detecting affected projects/packages
|
||||
|
||||
Optimizing for speed is crucial to be able to scale. One strategy is to leverage the knowledge about the monorepo workspace structure in combination with Git to determine what projects/packages might be affected by a given pull request.
|
||||
|
||||
- Both Nx and Turborepo support it.
|
||||
|
||||
Learn more about it in this [Egghead lesson on scaling CI runs with Nx Affected Commands](https://egghead.io/lessons/javascript-scale-ci-runs-with-nx-affected-commands).
|
||||
|
||||
#### 5. Local task coordination
|
||||
|
||||
Running multiple tasks in parallel, in the right order, on a single machine is crucial for a monorepo.
|
||||
|
||||
- Both Nx and Turborepo support it. And both can run different types of targets (e.g., tests and builds) as part of the same command.
|
||||
- **Everything in Nx is pluggable, including task coordination**. You can provide your own strategy (e.g., running multiple jest tasks using the jest monorepo mode when possible). Nx plugins supply custom strategies. Turborepos’s coordination logic at this point isn’t pluggable.
|
||||
|
||||
#### 6. Local computation caching
|
||||
|
||||
Local computation caching (often also refered to as "build caching") is the process of not having to run the same command twice, but rather to restore file artifacts and terminal outputs from a local cache. We refer to it as "computation caching", because in Nx you can really apply it to any type of task (not just builds).
|
||||
|
||||
- Both Nx and Turborepo support it.
|
||||
- **Turborepo always removes and recreates files on cache hits**, which is slow on Windows, and has other negative effects (if any tools watch those files). **Nx knows what files have been restored where and can leave the right files in the right place. It will only move the files about if the result would be different.** This is useful for when you build large applications incrementally or when you build a system out of microfrontends. In such cases the build command will often trigger hundreds of tasks, with the majority of them being cache hits. Constantly removing and restoring the files make this scenario much harder to implement.
|
||||
- Turborepo only uses piping to capture the terminal output. Piping doesn’t work well for the tasks emitting “interesting” output (cypress, webpack, etc). As a result, **the terminal output with Turborepo and without it doesn’t look the same**. Nx can use piping, but it also supports other strategies. As a result, Nx is able to capture the output “as is”. **Running say Cypress with Nx or without Nx results in the same output**, and the replayed output matches the original output exactly as well.
|
||||
- Once again, Nx is pluggable, so you can write plugins which determine what can affect a given computation, and some Nx plugins do that.
|
||||
|
||||
#### 7. Remote computation caching
|
||||
|
||||
Local computation caching helps speed up things locally, but the real benefits start when you distribute and share that cache remotely with your CI system and teammates.
|
||||
|
||||
- Both Nx and Turborepo support it.
|
||||
- Nx's recommended remote caching implementation is included with Nx Cloud. If enterprise clients are concerned about storing their cache data on shared infrastructure, Nx Cloud can be run on a single-tenant cloud server or we can create an on-prem solution. **Turborepo doesn't offer an on-prem solution.**
|
||||
- If you want to manage your own remote cache storage, you can [purchase a Powerpack license](/powerpack) and store the remote cache on a shared network drive or AWS S3 bucket.
|
||||
|
||||
#### 8. Distributed task execution
|
||||
|
||||
A crucial feature in Nx is the ability to not only parallelize your tasks on a single machine, but to be able to fully automatically distribute them across multiple machines. Nx makes sure they run in parallel, in the right order while still preserving the dev ergonomics as if all the tasks would be running on a single machine.
|
||||
|
||||
- **Nx supports distributed task execution.** It is able to run any command on multiple machines while preserving the dev experience of running it on a single machine: all the tasks execute in the right order, the terminal output is all in one place, the errors are all in one place, the files are all in one place. This is similar to what Bazel (a build tool used at Google) does. We got inspiration from it.
|
||||
- **Turborepo doesn’t support it.** The best thing you can do when using Turborepo is binning/sharding, and that doesn’t work for non-trivial workspaces.
|
||||
- **Distributed task execution has a significantly higher impact on the ability to scale the repo than the computation cache.** You can scale without the cache, you cannot scale without the distribution.
|
||||
- This is the biggest feature related to performance and scaling that Turborepo is missing. And it’s by far the hardest one to build.
|
||||
|
||||
If you want to learn more, check out our article on [Distributing CI - Binning and Distributed Task Execution](/blog/distributing-ci-binning-and-distributed-task-execution)
|
||||
|
||||
#### 9. Editor support
|
||||
|
||||
All the available Nx commands can be executed via the command line. But as your monorepo grows, with multiple teams and hundreds of projects, even just finding the project to run a command against can sometimes be difficult. Having a high quality IDE integration can be a time saver there.
|
||||
|
||||
- Nx has [VSCode](/getting-started/editor-setup) and WebStorm/Intellij plugins.
|
||||
- Turborepo doesn’t have any plugins, and the maintainer has indicated there's no intention to provide editor support.
|
||||
|
||||
Learn more [by watching this Egghead lesson](https://egghead.io/lessons/javascript-generate-new-projects-for-nx-with-nx-console).
|
||||
|
||||
#### 10. Configuration
|
||||
|
||||
Nx has grown over the last 5 years, providing curated presets for common setups, but at the same time focusing on remaining flexible and extensible.
|
||||
|
||||
- When it comes to Nx core, **the amount of the configuration Nx and Turborepo generate is the same**. Nx and Turborepo both generate a json file at the root of your workspace.
|
||||
- Both Nx and Turborepo allow you to define project specific configuration in separate files to ensure that changing those settings does not break the cache for the whole repository and to keep the configuration settings close to the related code.
|
||||
|
||||
Getting started quickly is very easy. Check out some of the examples below:
|
||||
|
||||
- [Video: Adding Nx to a PNPM based monorepo](https://youtu.be/8X2sGZn_ffY)
|
||||
- [Video: Nx with Minimal Configuration - Adding Nx to the Strapi repository](https://youtu.be/sVSLIyghhGo)
|
||||
- [Video: How Nx leverages package.json scripts in Nx 13.3](https://youtu.be/XOZkjDMxsA8)
|
||||
|
||||
#### 11. Transparency
|
||||
|
||||
Nx core make things faster but doesn't change how your commands run or how the terminal output looks. Compare Nx's and Turbo's terminal outputs:
|
||||
|
||||

|
||||
|
||||
Nx doesn't change your terminal output. Spinners, animations, colors are the same whether you use Nx or not (we instrument Node.js to get this result). What is also important is that when you restore things from cache, Nx will replay the terminal output identical to the one you would have had you run the command. Examine Turbo's output: no spinners, no animations, no colors. Pretty much anything you run with Turbo looks different (and in our opinion worse) from running the same command without Turbo.
|
||||
|
||||
A lot of Nx users don't even know they use Nx, or even what Nx is. Things they run look the same, they just got faster.
|
||||
|
||||
## Plugins and Supporting Features
|
||||
|
||||
The following set of features are tricky to compare. The scope of Nx is broader. **Having a monorepo doesn't just mean running things fast (scaling tech wise), it also means helping teams work effectively (scaling org-wise).** If your monorepo has 10 packages and is managed by a single team, then the org-wise scaling isn’t relevant, but for larger repos with thousands of projects and hundreds or thousands of contributors (an enterprise system) org scaling is just important (or perhaps more important) than the tech scaling.
|
||||
|
||||
Some of the things you need to do to scale org-wise:
|
||||
|
||||
- Folks can run tests for the project they never worked on. They examine the flags etc.
|
||||
- Folks can create artifacts, consistently. They can change them consistently (e.g., to move to the new API).
|
||||
- Folks can migrate to the newer versions of third-party deps (e.g., React/Cypress/Storybook).
|
||||
- Folks can automate large scale refactorings across the whole monorepo.
|
||||
- Folks can see the test output for thousands of projects built on hundreds of machines (you cannot have them printed out to stdout, you won't make any sense of what is going on, because there are too many things printed out)
|
||||
- Folks have tools to analyze cache misses.
|
||||
- Folks can define visibility constraints.
|
||||
- ...
|
||||
|
||||
Nx helps with these by using plugins and the Nx Cloud web app. For example, you can view the output of a distributed command that ran on 50 machines in a single place in Nx Cloud (and optionally you can even integrate it into your GitHub PR). It allows you to analyze cache misses and task distribution, which helps when you need to debug your CI runs.
|
||||
|
||||
At this point, Turborepo doesn’t do any of that. So for a monorepo of any non-trivial size you will have to implement all of those things using some other tools.
|
||||
|
||||
Nx is like the **VSCode of build tools**. In VSCode you can get started with the plain, core VSCode setup and it would be fine. But if you want to enhance your experience, there's the option to add extensions for managing Git, Docker, Mongo etc. Similarly, **you don’t have to use all the Nx plugins or, say, the Nx Cloud GitHub integration.**
|
||||
Nx doesn’t replace any of your tools, and it’s not “all in”. You can start without any Nx plugins and Nx Cloud affordances, as with Turborepo. Or you can add them in as you go, both natively supported plugins by Nx as well as our growing [set of community plugins](/community). **Turborepo isn’t pluggable**, so if you use the same analogy, you would have to use different tools (GitTower, DataGrip, Mongo Compass) to meet the same needs.
|
||||
|
||||
## Tech and Performance
|
||||
|
||||
Turborepo is mostly written in Golang and Rust. Nx is mostly written in TypeScript, but most of the heavy computation in Nx is done by core Node.js capabilities and Rust modules, so performance isn’t affected by this.
|
||||
|
||||
Benchmarking is hard because a lot depends on what you are trying to run, in what environment, etc. This is one benchmark we use when measuring Nx perf: [Nx and Turbo benchmark](https://github.com/vsavkin/large-monorepo/). It is a repo with 5 Next.js apps. We are measuring how quickly Nx and Turbo can figure out what needs to be restored from cache, and how quickly they can do it.
|
||||
|
||||
This is the result:
|
||||

|
||||
|
||||
Nx is 4 times faster on the latest MBP. We have made several changes to [the benchmark](https://github.com/vsavkin/large-monorepo/) since it was released (removed the usage `npx` and addressed other concerns folks had), but the result remained roughly the same. Please check out the benchmark.
|
||||
|
||||
Why is it faster? Nx is in many ways akin to React in that it's doing tree diffing when restoring files from the cache. If the right files are in the right place, Nx won't touch them. Turbo blows everything away every time. Nx's version isn't just faster, it's also more useful (again similarly to tree diffing in React). Blowing everything away on every restoration means that if any tools watch the folders (which is common when you build large apps or build microfrontends), they are going to get confused or triggered for no reason. This is similar to how recreating the DOM from scratch isn't just slower, but results in worse UX. But even if you disable tree-diffing and make Nx do what Turbo does, it is still 1.7 times faster.
|
||||
|
||||
The cache restoration Turborepo provides might be fast enough for a lot of repos (3 seconds is still plenty fast). What matters for larger repos like this one is the ability to distribute any command across say 50 machines while preserving the dev ergonomics of running it on a single machine. Nx can do it. Bazel can do it (which Nx borrows some ideas from). Turbo can't.
|
||||
|
||||
The one advantage Turbo's Go implementation has, is that any time you run an Nx command you pay a ~70ms penalty to boot Node.js. If you test 1 project, you pay a 70ms penalty, if you test 1000 projects, it is still a 70ms penalty. We don’t think in practice it matters because most other CLIs (e.g,. yarn) have the same penalty. The real performance gains from both Nx and Turborepo are in how intelligently they reduce, cache, and in Nx's case, distribute tasks.
|
||||
|
||||
**Nx and Turborepo often have different philosophies of how workspaces should be built.** Turborepo tends to think in terms of "packages", whereas Nx is focused on many lightweight projects. Large Nx Workspaces tend to be composed of hundreds or even thousands of projects, which helps the average build performance in three ways:
|
||||
|
||||
- Smaller portions of the graph are affected on average
|
||||
- There are more opportunities for partial cache hits
|
||||
- Distributed task execution has more flexibility in how it can distribute work across agents
|
||||
|
||||
**The reason why we stuck with TypeScript is that our focus was always on extensibility.** If the rise of VSCode taught us anything, it is that it’s easier to extend things when they are written in JavaScript/TypeScript. Also, 5 years of **working with Fortune 500 companies** clearly showed us that **extensibility is key**!
|
||||
|
||||
It’s also worth noting that the backend of Nx Cloud is written in Kotlin. This is because the only contributors to our API work at Nx, and we decided it was the best technology for the job.
|
||||
|
||||
## Community
|
||||
|
||||
Nx was released in 2016. Turborepo was open sourced in December of 2021. Turborepo doesn't have a large community yet, but it probably will at some point.
|
||||
|
||||
- There are about [4 million downloads per week](https://www.npmjs.com/package/nx).
|
||||
- There are about 1 million+ unique [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) (a plugin for VSCode) installations.
|
||||
- There is a rich ecosystem of [third-party plugins](/plugin-registry).
|
||||
|
||||
## Switch to Nx
|
||||
|
||||
If you're ready to switch from Turborepo to Nx, the [migration process is fully documented](/recipes/adopting-nx/from-turborepo).
|
||||
@ -24,7 +24,7 @@ Nx's features can be enabled in each of these types of repositories. Just as eac
|
||||
|
||||
A package-based repo is a collection of packages that depend on each other via `package.json` files and nested `node_modules`. With this setup, you typically have [different dependencies for each project](/concepts/decisions/dependency-management). Build tools like Jest and Webpack work as usual, since everything is resolved as if each package was in a separate repo and all of its dependencies were published to npm. Moving an existing package into a package-based repo is very easy since you generally leave that package's existing build tooling untouched. Creating a new package inside the repo is just as difficult as spinning up a new repo since you have to create all the build tooling from scratch.
|
||||
|
||||
Lerna, Yarn, Lage, [Turborepo](/concepts/turbo-and-nx) and Nx support this style.
|
||||
Lerna, Yarn, Lage, [Turborepo](/recipes/adopting-nx/from-turborepo) and Nx support this style.
|
||||
|
||||
Someone who appreciates the flexibility of a package-based repository will be most interested in the following features of Nx:
|
||||
|
||||
|
||||
@ -25926,10 +25926,6 @@
|
||||
"file": "docs/shared/guides/storybook/storybook-v6-react.md",
|
||||
"hash": "9c3412bebb5b28cd0dc760336b7fe6db83513866"
|
||||
},
|
||||
{
|
||||
"file": "docs/shared/guides/turbo-and-nx.md",
|
||||
"hash": "46a5d13d0423779797199acd8d36bae3812a3976"
|
||||
},
|
||||
{
|
||||
"file": "docs/shared/guides/use-environment-variables-in-angular.md",
|
||||
"hash": "4ee6708f2e8a84fb2f1fe1e48464a297059d728b"
|
||||
|
||||
@ -419,7 +419,7 @@ documentation" url="/concepts/task-pipeline-configuration" /%}
|
||||
{% card title="Nx Ignore" description="Learn about how to ignore certain projects using .nxignore" type="documentation"
|
||||
url="/reference/nxignore" /%}
|
||||
|
||||
{% card title="Nx and Turbo" description="Read about how Nx compares to Turborepo" url="
|
||||
/concepts/turbo-and-nx" /%}
|
||||
{% card title="Migrating from Turborepo to Nx" description="Read about Migrating from Turborepo to Nx" url="
|
||||
/recipes/adopting-nx/from-turborepo" /%}
|
||||
|
||||
{% /cards %}
|
||||
|
||||
@ -1,160 +1,283 @@
|
||||
# Migrate from Turborepo to Nx
|
||||
# Migrating from Turborepo to Nx
|
||||
|
||||
If you have an existing monorepo that uses Turborepo, switching to use Nx is a straight-forward process. After switching, you'll have cleaner CLI output, a better graph view and IDE support with the option to incorporate [Nx plugins](/concepts/nx-plugins). All this without increasing the complexity of your configuration files.
|
||||
{% callout type="note" title="Already know you want to migrate?" %}
|
||||
Jump to:
|
||||
|
||||
For more details, read our [comparison of Nx and Turborepo](/concepts/turbo-and-nx)
|
||||
- [Easy Automated Migration Example](#easy-automated-migration-example) - Automated migration from `create-turbo` workspace using `nx init`
|
||||
|
||||
## Initialize Nx
|
||||
**Spoiler alert:** The diff is tiny! Nx is a superset of Turborepo, so it can already do everything Turborepo can do without any extra configuration.
|
||||
|
||||
To switch to Nx, run this command:
|
||||
```diff
|
||||
.gitignore | 3 +++ # Ignore the Nx cache
|
||||
package.json | 1 + # Add the "nx" package
|
||||
package-lock.json |
|
||||
nx.json | # Equivalent to turbo.json
|
||||
```
|
||||
|
||||
{% /callout %}
|
||||
|
||||
- [Configuration Migration Guide](#configuration-migration-guide) - How to mentally map Turborepo configuration to Nx configuration
|
||||
- [Command Equivalents](#command-equivalents) - How to mentally map Turborepo commands to Nx commands
|
||||
|
||||
## Why Migrate to Nx?
|
||||
|
||||
### 1. Superior Performance through Smarter Computation Caching
|
||||
|
||||
**Nx is significantly faster than Turborepo**, with open-source benchmarks showing more then 7x better performance in large monorepos. This is publicly verifiable here: [large-monorepo benchmark](https://github.com/vsavkin/large-monorepo).
|
||||
|
||||
The performance difference is particularly noticeable in larger, real-world monorepos, such as the one used in the benchmark.
|
||||
|
||||

|
||||
|
||||
This isn't just about raw speed - Nx's approach to file restoration means it's both faster and more reliable, especially when working with tools that watch files.
|
||||
|
||||
### 2. Fast CI
|
||||
|
||||
**Just like Turborepo, Nx provides FREE remote caching to small teams, both self-hosted and via its own cloud** (Vercel in the case of Turborepo, Nx Cloud (https://nx.app) in the case of Nx). And just like Turborepo, Nx provides paid plans for larger, more sophisticated teams that need a higher level of service. For self-hosted remote caching, small teams can apply for FREE Nx Powerpack License here: https://nx.app/powerpack
|
||||
|
||||
However, unlike Turborepo, Nx's CI solution (Nx Cloud) goes way beyond just locating a shared cache on a server somewhere.
|
||||
|
||||
Nx Cloud allows you to ship updates to your users faster and with more confidence than ever before thanks to:
|
||||
|
||||
- Intelligently distributing your tasks across multiple machines without any manual "binning" configuration. Nx knows your workspace so let it decide what should run in what order.
|
||||
- File artifacts automatically collected and distributed
|
||||
- Built in support for versioning, changelog generation and publishing via [Nx Release](/features/manage-releases)
|
||||
- Finally solving the pain of long-running, flaky e2e tests by:
|
||||
- Automatically splitting up a single e2e test task into multiple tasks that can run in parallel _across multiple machines_ thanks to Atomizer: https://nx.dev/ci/features/split-e2e-tasks
|
||||
- Automatically detects and rerun flaky tasks: https://nx.dev/ci/features/flaky-tasks
|
||||
|
||||
This is crucial for scaling large monorepos, as distributed task execution has a significantly higher impact on scalability than computation caching alone. You can scale without caching, but you cannot scale without distribution.
|
||||
|
||||
### 3. Supports you all the way from vanilla package manager workspaces through to advanced Enterprise Monorepos
|
||||
|
||||
**Nx works effortlessly with zero plugins with industry standard package manager workspaces from `npm`, `yarn`, `pnpm` and `bun`**. Turborepo also works with these, but that's where it starts and ends.
|
||||
|
||||
Nx additionally works with any programming language, framework and tooling. The core of Nx is written in Rust for speed and TypeScript for extensibility, with a first-class plugin API for both task execution and project/dependency graph analysis.
|
||||
|
||||
This means that you do not need to add `package.json` files for languages like Rust, Java, Go, .NET, etc. that do not require them, and instead can install their respective Nx plugins.
|
||||
|
||||
Turborepo forces you to manually annotated your non-JavaScript packages, Nx understands it all through its first-class plugins, making it suitable for everything from open-source JavaScript tools with a handful of `npm` packages through to the largest enterprise-grade polyglot/multi-languages monorepos.
|
||||
|
||||
### 4. Superior Developer Experience
|
||||
|
||||
#### Rich Visualization
|
||||
|
||||
Being able to visually explore your workspace is crucial for large monorepos:
|
||||
|
||||
- **Nx**: Rich, interactive visualizer, both locally via the `nx graph` CLI ([watch demo](https://www.youtube.com/watch?v=UTB5dOJF43o)) and for every pull request via Nx Cloud.
|
||||
- **Turborepo**: Basic graphviz image export
|
||||
|
||||
#### IDE/Developer Tools
|
||||
|
||||
- **Nx**: provides powerful VSCode and WebStorm/IntelliJ extensions with nearly 2 million installations. Run tasks, code generators, the graph visualizer, interact with Nx Cloud CI runs and more.
|
||||
- **Turborepo**: provides basic LSP support
|
||||
|
||||
### 5. Plugin System and Organizational Scaling
|
||||
|
||||
Nx is like the **VSCode of build tools**. Just as VSCode provides a core experience that can be enhanced with extensions for Git, Docker, MongoDB etc., Nx offers:
|
||||
|
||||
- Core functionality that works out of the box
|
||||
- Rich plugin ecosystem for enhanced capabilities
|
||||
- Community plugins for additional tools and frameworks
|
||||
- Custom plugin development for organization-specific needs
|
||||
|
||||
This plugin system helps teams scale organizationally by:
|
||||
|
||||
- Enabling consistent task execution across all projects
|
||||
- Automating large-scale refactorings
|
||||
- Providing tools to analyze cache misses
|
||||
- Supporting visibility constraints
|
||||
|
||||
### 6. Enterprise-Ready Features
|
||||
|
||||
- Conformance rules for consistently enforcing best practices across your organization
|
||||
- On-premise and single-tenant Nx Cloud options
|
||||
- Distributed task execution (similar to Google's Bazel)
|
||||
- Advanced GitHub integration
|
||||
- Comprehensive analytics and insights
|
||||
- Module boundary rules essential for multi-team monorepos
|
||||
|
||||
### 7. Thriving Community
|
||||
|
||||
Nx has been battle-tested since 2016:
|
||||
|
||||
- ~5 million downloads per week
|
||||
- Nearly 2 million unique [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) installations
|
||||
- Rich ecosystem of [third-party plugins](/plugin-registry), many with millions of downloads in their own right
|
||||
- Used by over half of Fortune 500 companies in production
|
||||
|
||||
### 8. Incremental Adoption
|
||||
|
||||
Nx can be added to a repo with almost no friction. You can incrementally enable plugins and supporting features that are not available with Turborepo.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
- [Article: A New Nx Experience for TypeScript Monorepos and Beyond](/blog/new-nx-experience-for-typescript-monorepos)
|
||||
- [Video: Automatically Keep Your Codebase Updated](https://www.youtube.com/watch?v=A0FjwsTlZ8A)
|
||||
- [Video: From PNPM Monorepo to Fast CI](https://www.youtube.com/watch?v=zX-1tpqUG5c)
|
||||
- [Video: AI-powered Debugging with Nx Cloud](https://www.youtube.com/watch?v=g2m9cHp-O-Q)
|
||||
|
||||
## Easy Automated Migration Example
|
||||
|
||||
The simplest way to understand the concepts is to see a basic migration example.
|
||||
|
||||
1. Let's create a new Turborepo workspace using the recommended `create-turbo` command:
|
||||
|
||||
```shell
|
||||
npx create-turbo@latest
|
||||
```
|
||||
|
||||
2. Once that is finished, literally all we need to do make it a valid Nx workspace is run `nx init`:
|
||||
|
||||
```shell
|
||||
npx nx@latest init
|
||||
```
|
||||
|
||||
See the [Adding Nx to NPM/Yarn/PNPM Workspace](/recipes/adopting-nx/adding-to-monorepo) guide for details about everything the `nx init` command does.
|
||||
That's it! As you can see, the diff is tiny:
|
||||
|
||||
## Convert turbo.json into Nx Configuration
|
||||
```diff
|
||||
.gitignore | 3 +++ # Ignore the Nx cache
|
||||
package.json | 1 + # Add the "nx" package
|
||||
package-lock.json |
|
||||
nx.json | # Equivalent to turbo.json
|
||||
```
|
||||
|
||||
Most of the settings in your `turbo.json` file can be converted directly into `nx.json` equivalents. The key configuration properties of `dependsOn`, `inputs` and `outputs` have a very similar syntax and can probably be copied over directly from the `turbo.json` `tasks` into the `nx.json` `targetDefaults`.
|
||||
- An `nx.json` file that is equivalent to the `turbo.json` file was added
|
||||
- The `package.json` file was updated to add the `nx` dev dependency (and the package-lock.json was updated accordingly)
|
||||
- The .gitignore entry for the Nx cache was added automatically
|
||||
|
||||
If you have project-specific tasks defined in the root `turbo.json` (i.e. `myreactapp#build`) or in project-level `turbo.json` files (i.e. `/packages/myreactapp/turbo.json`), those settings should go in the `nx` property of the project's `package.json` (i.e. `/packages/myreactapp/package.json`).
|
||||
It's important to remember that Nx is a superset of Turborepo, it can do everything Turborepo can do and much more, so there is absolutely no special configuration needed for Nx, it just works on the Turborepo workspace.
|
||||
|
||||
[Specific configuration property conversions](#specific-configuration-property-conversions) are documented below.
|
||||
### Example: Basic Configuration Comparison
|
||||
|
||||
## Example
|
||||
To help with understanding the new `nx.json` file, let's compare it to the `turbo.json` file:
|
||||
|
||||
Let's say you start with the following `turbo.json` file:
|
||||
|
||||
```json {% fileName="/turbo.json" %}
|
||||
```json
|
||||
{
|
||||
"$schema": "https://turbo.build/schema.json",
|
||||
// Nx will automatically use an appropriate terminal output style for the tasks you run
|
||||
"ui": "tui",
|
||||
"tasks": {
|
||||
"build": {
|
||||
// This syntax of build depending on the build of its dependencies using ^ is the same
|
||||
// in Nx
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**"]
|
||||
// Inputs and outputs are in Turborepo are relative to a particular package, whereas in Nx they are consistently from the workspace root and it therefore has {projectRoot} and {projectName} helpers
|
||||
"inputs": ["$TURBO_DEFAULT$", ".env*"],
|
||||
"outputs": [".next/**", "!.next/cache/**"]
|
||||
},
|
||||
"docs#build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["www/**"]
|
||||
"lint": {
|
||||
// Turborepo tasks are assumed to be cacheable by default, so there is no recognizable configuration here. In Nx, the "cache" value is clearly set to true.
|
||||
"dependsOn": ["^lint"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["build"],
|
||||
"outputs": []
|
||||
"check-types": {
|
||||
"dependsOn": ["^check-types"]
|
||||
},
|
||||
"e2e": {
|
||||
"dependsOn": ["build"],
|
||||
"outputs": []
|
||||
"dev": {
|
||||
"cache": false,
|
||||
// Nx has a powerful "continuous" setting for tasks in beta which even works across
|
||||
// multiple machines. This is going to be generally available in Nx 21 and it will be a
|
||||
// superset of Turborepo's "persistent" setting.
|
||||
"persistent": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"globalDependencies": ["babel.config.json"]
|
||||
}
|
||||
```
|
||||
|
||||
Creating the equivalent configuration with Nx yields the following files:
|
||||
After running `nx init`, you'll automatically have an equivalent `nx.json`:
|
||||
|
||||
```json {% fileName="/nx.json" %}
|
||||
```json
|
||||
{
|
||||
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||
"namedInputs": {
|
||||
"sharedGlobals": ["babel.config.json"],
|
||||
"default": ["{projectRoot}/**/*", "sharedGlobals"]
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"inputs": ["default"],
|
||||
"outputs": ["{projectRoot}/dist"],
|
||||
"inputs": ["{projectRoot}/**/*", "{projectRoot}/.env*"],
|
||||
"outputs": ["{projectRoot}/.next/**", "!{projectRoot}/.next/cache/**"],
|
||||
"cache": true
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["build"],
|
||||
"inputs": ["default"],
|
||||
"lint": {
|
||||
"dependsOn": ["^lint"],
|
||||
"cache": true
|
||||
},
|
||||
"e2e": {
|
||||
"dependsOn": ["build"],
|
||||
"inputs": ["default"],
|
||||
"check-types": {
|
||||
"dependsOn": ["^check-types"],
|
||||
"cache": true
|
||||
}
|
||||
},
|
||||
"nxCloudId": "..."
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc {% fileName="/packages/docs/package.json" %}
|
||||
{
|
||||
"name": "docs",
|
||||
// etc...
|
||||
"nx": {
|
||||
"targets": {
|
||||
"build": {
|
||||
"outputs": ["www/**"]
|
||||
}
|
||||
"dev": {
|
||||
"cache": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Specific Configuration Property Conversions
|
||||
## Configuration Migration Guide
|
||||
|
||||
For each `turbo.json` configuration property, the equivalent Nx property is listed.
|
||||
Most settings in the old `turbo.json` file can be converted directly into `nx.json` equivalents. Here's how to map each configuration property:
|
||||
|
||||
| **Global Configuration:** | |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
### Global Configuration
|
||||
|
||||
| Turborepo Property | Nx Equivalent |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `cacheDir` | Set in [`cacheDirectory`](/reference/nx-json#task-options) |
|
||||
| `deamon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/nx-daemon#turning-it-off) in `nx.json` |
|
||||
| `envMode` | Nx core does not block any environment variables. There are [React](/recipes/react/use-environment-variables-in-react) and [Angular](/recipes/angular/use-environment-variables-in-angular) build executors that handle environment variables in a customized way. |
|
||||
| `globalDependencies` | add to the [`sharedGlobals` `namedInput`](/recipes/running-tasks/configure-inputs) |
|
||||
| `globalEnv` | add to the [`sharedGlobals` `namedInput`](/recipes/running-tasks/configure-inputs) as an [`env` input](/reference/inputs#environment-variables) |
|
||||
| `daemon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/nx-daemon#turning-it-off) in `nx.json` |
|
||||
| `envMode` | Nx core does not block any environment variables. See [React](/recipes/react/use-environment-variables-in-react) and [Angular](/recipes/angular/use-environment-variables-in-angular) guides |
|
||||
| `globalDependencies` | Add to the [`sharedGlobals` `namedInput`](/recipes/running-tasks/configure-inputs) |
|
||||
| `globalEnv` | Add to the [`sharedGlobals` `namedInput`](/recipes/running-tasks/configure-inputs) as an [`env` input](/reference/inputs#environment-variables) |
|
||||
| `globalPassThroughEnv` | N/A. See [Defining Environment Variables](/recipes/tips-n-tricks/define-environment-variables) |
|
||||
| `remoteCache` | See [Nx Replay](/ci/features/remote-cache) |
|
||||
| `ui` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
|
||||
| **Task Configuration:** | |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| `extends` | N/A. The project configurations will always extend the `targetDefaults` defined in `nx.json`. |
|
||||
| `tasks[task].dependsOn` | [Same syntax](/reference/project-configuration#dependson). |
|
||||
| `tasks[task].env` | Define [env `inputs`](/reference/inputs#environment-variables) |
|
||||
| `tasks[task].passThroughEnv` | N/A. See [Defining Environment Variables](/recipes/tips-n-tricks/define-environment-variables) |
|
||||
| `tasks[task].outputs` | [Same syntax](/reference/project-configuration#outputs). |
|
||||
| `tasks[task].cache` | [Same syntax](/reference/project-configuration#cache) |
|
||||
| `tasks[task].inputs` | [Same syntax](/reference/inputs#source-files). |
|
||||
| `tasks[task].outputLogs` | Use the [`--output-style` command line flag](/nx-api/nx/documents/run-many#output-style) |
|
||||
| `tasks[task].persistent` | N/A. |
|
||||
| `tasks[task].interactive` | N/A. |
|
||||
| `ui` | Nx will intelligently pick the most appropriate terminal output style, but it can be overridden with [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
|
||||
|
||||
### Task Configuration
|
||||
|
||||
| Turborepo Property | Nx Equivalent |
|
||||
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `extends` | N/A. Projects always extend `targetDefaults` from `nx.json` |
|
||||
| `dependsOn` | [Same syntax](/reference/project-configuration#dependson) |
|
||||
| `env` | Define [env `inputs`](/reference/inputs#environment-variables) |
|
||||
| `passThroughEnv` | N/A. See [Defining Environment Variables](/recipes/tips-n-tricks/define-environment-variables) |
|
||||
| `outputs` | [Similar syntax](/reference/project-configuration#outputs) |
|
||||
| `cache` | [Similar syntax](/reference/project-configuration#cache) |
|
||||
| `inputs` | [Similar syntax](/reference/inputs#source-files) |
|
||||
| `outputLogs` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
|
||||
| `persistent` | Nx has a powerful "continuous" setting for tasks in beta which even works across multiple machines. This is going to be generally available in Nx 21 and it will be a superset of Turborepo's "persistent" setting. |
|
||||
| `interactive` | All "continuous" tasks (coming in Nx 21) are intelligently and automatically interactive. |
|
||||
|
||||
## Command Equivalents
|
||||
|
||||
| | |
|
||||
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
Here's how Turborepo commands map to Nx:
|
||||
|
||||
| Turborepo Command | Nx Equivalent |
|
||||
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `turbo run test lint build` | [`nx run-many -t test lint build`](/nx-api/nx/documents/run-many) |
|
||||
| `--cache-dir` | Set in [`nx.json` under `cacheDirectory`](/reference/nx-json#task-options) |
|
||||
| `--concurrency` | [`--parallel`](/nx-api/nx/documents/run-many#parallel) |
|
||||
| `--continue` | [Use `--nx-bail`](/nx-api/nx/documents/run-many#nx-bail) with the inverse value |
|
||||
| `--cpuprofile` | Use [`NX_PROFILE=profile.json`](/troubleshooting/performance-profiling). |
|
||||
| `--cwd` | Available when using the [`run-commands` executor](/nx-api/nx/executors/run-commands#cwd) |
|
||||
| `--deamon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/nx-daemon#turning-it-off) in `nx.json` |
|
||||
| `--dry-run` | N/A. Nx has `--dry-run` for `nx generate` but not for running tasks. |
|
||||
| `--env-mode` | Nx core does not block any environment variables. There are [React](/recipes/react/use-environment-variables-in-react) and [Angular](/recipes/angular/use-environment-variables-in-angular) build executors that handle environment variables in a customized way. |
|
||||
| `--filter` | Use [`-p admin-*` or `-p tag:api-*`](/nx-api/nx/documents/run-many#projects). Also see [`nx affected`](/nx-api/nx/documents/affected). |
|
||||
| `--cpuprofile` | Use [`NX_PROFILE=profile.json`](/troubleshooting/performance-profiling) |
|
||||
| `--cwd` | Available in [`run-commands` executor](/nx-api/nx/executors/run-commands#cwd) |
|
||||
| `--daemon` | Use [`NX_DAEMON=false` or set `useDaemonProcess: false`](/concepts/nx-daemon#turning-it-off) |
|
||||
| `--dry-run` | N/A. Nx has `--dry-run` for `nx generate` but not for running tasks |
|
||||
| `--env-mode` | See [React](/recipes/react/use-environment-variables-in-react) and [Angular](/recipes/angular/use-environment-variables-in-angular) guides |
|
||||
| `--filter` | Use lots of advanced project matcher syntax like [`-p admin-*` or `-p tag:api-*`](/nx-api/nx/documents/run-many#projects) |
|
||||
| `--force` | [`nx reset`](/nx-api/nx/documents/reset) and then run the command again |
|
||||
| `--framework-inference` | Nx knows if you're using a particular framework if you use an executor for that framework. |
|
||||
| `--global-deps` | Use [`inputs` in the `nx.json`](/recipes/running-tasks/configure-inputs) or project configuration |
|
||||
| `--graph` | [Same syntax](/nx-api/nx/documents/run-many#graph) or [`nx graph`](/nx-api/nx/documents/dep-graph) for the entire graph |
|
||||
| `--heap` | N/A. [`--verbose`](/nx-api/nx/documents/run-many#verbose) for more logging. |
|
||||
| `--ignore` | Use an [`.nxignore` file](/reference/nxignore) (or `.gitignore`) |
|
||||
| `--framework-inference` | N/A. [Nx plugins infer tasks automatically as a first class feature](/concepts/inferred-tasks) |
|
||||
| `--global-deps` | Use [`inputs` in `nx.json`](/recipes/running-tasks/configure-inputs) |
|
||||
| `--graph` | [Similar syntax](/nx-api/nx/documents/run-many#graph) or [`nx graph`](/nx-api/nx/documents/dep-graph) for full interactive experience |
|
||||
| `--heap` | N/A. Use [`--verbose`](/nx-api/nx/documents/run-many#verbose) |
|
||||
| `--ignore` | Use [`.nxignore`](/reference/nxignore) or `.gitignore` |
|
||||
| `--log-order` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
|
||||
| `--no-cache` | Use [`--skip-nx-cache`](/nx-api/nx/documents/run-many#skip-nx-cache) |
|
||||
| `--output-logs` | Use [`--output-style`](/nx-api/nx/documents/run-many#output-style) |
|
||||
| `--only` | N/A |
|
||||
| `--parallel` | N/A |
|
||||
| `--preflight` | N/A |
|
||||
| `--remote-only` | N/A. Can [ignore the remote cache](/ci/features/remote-cache#skipping-cloud-cache) with `--no-cloud`. |
|
||||
| `--summarize` | N/A |
|
||||
| `--token` | Set the [Nx Cloud CI Access Token](/ci/recipes/security/access-tokens#setting-ci-access-tokens) or as an environment variable (`NX_CLOUD_ACCESS_TOKEN`) |
|
||||
| `--team` | See `--token` for choosing a different Nx Cloud workspace. You can [use `--runner`](/nx-api/nx/documents/run-many#runner) to choose a different runner defined in the `nx.json` file. |
|
||||
| `--trace` | N/A. [`--verbose`](/nx-api/nx/documents/run-many#verbose) for more logging. |
|
||||
| `--token` | Set [Nx Cloud CI Access Token](/ci/recipes/security/access-tokens#setting-ci-access-tokens) |
|
||||
| `--team` | See `--token` for Nx Cloud workspace selection |
|
||||
| `--trace` | N/A. Use [`--verbose`](/nx-api/nx/documents/run-many#verbose) |
|
||||
| `--verbosity` | Use [`--verbose`](/nx-api/nx/documents/run-many#verbose) |
|
||||
| `turbo gen` | [Use `nx generate`](/nx-api/nx/documents/generate) |
|
||||
| `turbo login` | No need. [Create an Nx Cloud account](/nx-api/nx/documents/connect-to-nx-cloud) once to set up Nx Cloud. |
|
||||
| `turbo link` | [Create an Nx Cloud account](/nx-api/nx/documents/connect-to-nx-cloud) |
|
||||
| `turbo login` | `nx login` - [Create an Nx Cloud account](/nx-api/nx/documents/connect-to-nx-cloud) |
|
||||
| `turbo link` | `nx connect` - [Connect a workspace to an Nx Cloud account](/nx-api/nx/documents/connect-to-nx-cloud) |
|
||||
|
||||
For a complete list of Nx commands and options, see the [Nx CLI documentation](/nx-api/nx).
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
- [Nx Daemon](/concepts/nx-daemon)
|
||||
- [Sync Generators](/concepts/sync-generators)
|
||||
- [TypeScript Project Linking](/concepts/typescript-project-linking)
|
||||
- [Nx and Turborepo](/concepts/turbo-and-nx)
|
||||
- [Buildable and Publishable Libraries](/concepts/buildable-and-publishable-libraries)
|
||||
- [Module Federation](/concepts/module-federation)
|
||||
- [Module Federation and Nx](/concepts/module-federation/module-federation-and-nx)
|
||||
|
||||
@ -259,7 +259,7 @@ const diataxis = {
|
||||
'/ci/distributed-builds': '/nx-cloud/concepts/parallelization-distribution', // 👀
|
||||
'/ci/setup-incremental-builds-angular':
|
||||
'/recipes/other/setup-incremental-builds-angular',
|
||||
'/guides/turbo-and-nx': '/concepts/more-concepts/turbo-and-nx',
|
||||
'/guides/turbo-and-nx': '/recipes/adopting-nx/from-turborepo',
|
||||
'/guides/why-monorepos': '/concepts/more-concepts/why-monorepos',
|
||||
'/guides/adding-assets-react': '/recipes/other/adding-assets-react',
|
||||
'/guides/environment-variables': '/reference/environment-variables',
|
||||
@ -795,6 +795,7 @@ const conceptUrls = {
|
||||
'/nx-api/angular/documents/nx-devkit-angular-devkit',
|
||||
'/concepts/more-concepts/incremental-builds':
|
||||
'/concepts/more-concepts/buildable-and-publishable-libraries',
|
||||
'/concepts/turbo-and-nx': '/recipes/adopting-nx/from-turborepo',
|
||||
};
|
||||
|
||||
const nested5minuteTutorialUrls = {
|
||||
@ -1123,7 +1124,7 @@ const decisionsSection = {
|
||||
'/concepts/decisions/project-dependency-rules',
|
||||
'/concepts/more-concepts/grouping-libraries':
|
||||
'/concepts/decisions/folder-structure',
|
||||
'/concepts/more-concepts/turbo-and-nx': '/concepts/turbo-and-nx',
|
||||
'/concepts/more-concepts/turbo-and-nx': '/recipes/adopting-nx/from-turborepo',
|
||||
'/concepts/more-concepts/nx-daemon': '/concepts/nx-daemon',
|
||||
'/concepts/more-concepts/buildable-and-publishable-libraries':
|
||||
'/concepts/buildable-and-publishable-libraries',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user