-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Documentation for Workspace Configs (#3788)
Co-authored-by: Nicholas Yang <nicholas.yang@vercel.com> Co-authored-by: Chris Olszewski <chris.olszewski@vercel.com> Co-authored-by: Rich Haines <hello@richardhaines.dev>
- Loading branch information
1 parent
a313e24
commit 9fec98e
Showing
2 changed files
with
278 additions
and
3 deletions.
There are no files selected for viewing
266 changes: 266 additions & 0 deletions
266
docs/pages/repo/docs/core-concepts/monorepos/configuring-workspaces.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
--- | ||
title: Configuring Workspaces | ||
description: Turborepo lets you configure each workspace | ||
--- | ||
|
||
import Callout from "../../../../../components/Callout"; | ||
|
||
# Configuring Workspaces | ||
|
||
Most monorepos can declare a `turbo.json` in the root directory with a uniform | ||
[pipeline][2] that apply to all workspaces. Sometimes, a monorepo can contain | ||
workspaces that need to configure their tasks differently. To accommodate this, | ||
starting in version 1.8, Turborepo enables you to extend the root configuration | ||
with a `turbo.json` in any workspace. This flexibility enables a more diverse | ||
set of apps and packages to co-exist, and allows workspace owners to maintain | ||
specialized tasks and configuration without affecting other apps and packages of | ||
the monorepo. | ||
|
||
## How it Works | ||
|
||
To override the configuration for any task defined in the root `turbo.json`, add | ||
a `turbo.json` file in any workspace of your monorepo with a top-level `extends` | ||
key: | ||
|
||
```jsonc filename="apps/my-app/turbo.json" | ||
{ | ||
"extends": ["//"], | ||
"pipeline": { | ||
"build": { | ||
// custom configuration for the build task in this workspace | ||
}, | ||
// new tasks only available in this workspace | ||
"special-task": {}, | ||
} | ||
} | ||
``` | ||
|
||
<Callout> | ||
For now, the only valid value for the `extends` key is `["//"]`. | ||
`//` is a special name used to identify the root directory of the monorepo. | ||
</Callout> | ||
|
||
Configuration in a workspace can override any of [the configurations for a | ||
pipeline task][2]. If you don't include a key, the configuration is inherited | ||
from the extended `turbo.json`. | ||
|
||
## Examples | ||
|
||
To illustrate, let's look at some use cases. | ||
|
||
### Different Frameworks | ||
|
||
Let's say your monorepo has multiple [Next.js][5] apps, and one [SvelteKit][6] | ||
app. Both frameworks create their build output with a `build` script in their | ||
respective `package.json`s. You _could_ configure Turborepo to run these tasks | ||
with a single `turbo.json` at the root like this: | ||
|
||
```jsonc filename="turbo.json" | ||
{ | ||
"pipeline": { | ||
"build": { | ||
"outputs": [".next/**", ".svelte-kit/**"], | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Notice that both `.next/**` and `.svelte-kit/**` need to be specified as | ||
[`outputs`][7], even though Next.js apps do not generate a `.svelte-kit` directory, and | ||
vice versa. With Workspace Configurations, you can instead add custom | ||
configuration in the SvelteKit workspace in `apps/my-svelte-kit-app/turbo.json`: | ||
|
||
```jsonc filename="apps/my-svelte-kit-app/turbo.json" | ||
{ | ||
"extends": ["//"], | ||
"pipeline": { | ||
"build": { | ||
"outputs": [".svelte-kit/**"] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
and remove the config from the root configuration: | ||
|
||
```diff filename="turbo.json" | ||
{ | ||
"pipeline": { | ||
"build": { | ||
- "outputs": [".next/**", ".svelte-kit/**"] | ||
+ "outputs": [".next/**"] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
This not only makes each configuration easier to read, it puts the configuration | ||
closer to where it is used. | ||
|
||
### Specialized Tasks | ||
|
||
In another example, say that the `build` task in one workspace `dependsOn` a | ||
`compile` task. You could universally declare it as `dependsOn: ["compile"]`. | ||
This means that your root `turbo.json` has to have an empty `compile` task | ||
entry: | ||
|
||
```json filename="turbo.json" | ||
{ | ||
"pipeline": { | ||
"build": { | ||
"dependsOn": ["compile"] | ||
}, | ||
"compile": {} | ||
} | ||
} | ||
``` | ||
|
||
With Workspace Configurations, you can move that `compile` task into the | ||
`apps/my-custom-app/turbo.json`, | ||
|
||
```json filename="apps/my-app/turbo.json" | ||
{ | ||
"extends": ["//"], | ||
"pipeline": { | ||
"build": { | ||
"dependsOn": ["compile"] | ||
}, | ||
"compile": {} | ||
} | ||
} | ||
``` | ||
|
||
and remove it from the root: | ||
|
||
```diff filename="turbo.json" | ||
{ | ||
"pipeline": { | ||
+ "build": {} | ||
- "build": { | ||
- "dependsOn": ["compile"] | ||
- }, | ||
- "compile": {} | ||
} | ||
} | ||
``` | ||
|
||
Now, the owners of `my-app`, can have full ownership over their `build` task, | ||
but continue to inherit any other tasks defined at the root. | ||
|
||
## Comparison to Workspace-specific tasks | ||
|
||
At first glance, Workspace Configurations may sound a lot like the | ||
[`workspace#task` syntax][3] in the root `turbo.json`. The features are | ||
similar, but have one significant difference: when you declare a Workspace-specific | ||
in the root `turbo.json`, it _completely_ overwrites the baseline task | ||
configuration. With a Workspace Configuration, the task configuration is merged | ||
instead. | ||
|
||
Consider the example of the monorepo with multiple Next.js apps and a Sveltekit | ||
app again. Without a Workspace-specific task, you might configure your root | ||
`turbo.json` like this: | ||
|
||
```jsonc filename="turbo.json" | ||
{ | ||
"pipeline": { | ||
"build": { | ||
"outputMode": "hash-only", | ||
"inputs": ["src/**"], | ||
"outputs": [".next/**"], | ||
}, | ||
"my-sveltekit-app#build": { | ||
"outputMode": "hash-only", // must duplicate this | ||
"inputs": ["src/**"], // must duplicate this | ||
"outputs": [".svelte-kit/**"] | ||
} | ||
} | ||
} | ||
``` | ||
|
||
This works, but it's important to understand that the `my-sveltekit-app#build` | ||
completely ovewrites `build` for the Sveltekit app. Any other config (such as | ||
`outputMode`) in the `build` task would need to be duplicated. With Workspace | ||
Configurations, you don't need to duplicate any configuration. Just override | ||
what needs to be changed. | ||
|
||
<Callout type="info"> | ||
Although there are no plans to remove Workspace-specific task configurations, | ||
we expect that Workspace Configurations can be used for most use cases instead. | ||
</Callout> | ||
|
||
## Limitations | ||
|
||
Although the general idea is the same as the root `turbo.json`, Workspace | ||
Configurations come with a set of guardrails that can prevent workspaces from creating | ||
confusing situations. These guardrails are listed here to make it clear that | ||
they are intentional, rather than accidental: | ||
|
||
- Workspace Configurations cannot use [the `workspace#task` syntax][3] as pipeline entries | ||
|
||
The `workspace` is inferred based on the _location_ of the config, and it is | ||
not possible to change configuration for another workspace. For example, in a | ||
Workspace Configuration for 'my-nextjs-app': | ||
|
||
```jsonc filename="apps/my-nextjs-app/turbo.json" | ||
{ | ||
"pipeline": { | ||
"my-nextjs-app#build": { | ||
// ❌ This is not allowed. Even though it's | ||
// referencing the correct workspace, "my-nextjs-app" | ||
// is inferred, and we don't need to specify it again. | ||
// This syntax also has different behavior, so we do not want to allow it. | ||
// (see "Comparison to Workspace-specific tasks" section) | ||
}, | ||
"my-sveltekit-app#build": { | ||
// ❌ Changing configuration for the "my-sveltekit-app" workspace | ||
// from Workspace Configuraton in "my-nextjs-app" is not allowed. | ||
}, | ||
"build": { | ||
// ✅ just use the task name! | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
Note that the `build` task can still depend on a Workspace-specific task: | ||
|
||
```jsonc filename="apps/my-nextjs-app/turbo.json" | ||
{ | ||
"pipeline": { | ||
"build": { | ||
// ✅ It's still ok to have workspace#task in dependsOn! | ||
"dependsOn": ["some-pkg#compile"] | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
- Workspace Configurations cannot override anything outside the `pipeline` key. | ||
|
||
For example, it is not possible to override `globalEnv` or | ||
`globalDependencies`. We expect that monorepo owners should control this | ||
absolutely, and if this config is not _truly_ global, it should not be | ||
configured that way. | ||
|
||
- Root turbo.json cannot use the `extends` key. | ||
|
||
To avoid creating circular dependencies on workspaces, the root `turbo.json` | ||
cannot extend from anything. | ||
|
||
If you have a use case for any of these, please [file an issue][4]! | ||
|
||
## Troubleshooting | ||
|
||
In large monorepos, it can sometimes be difficult to understand how Turborepo is | ||
interpreting your configuration. To help, we've added a `resolvedTaskDefinition` | ||
to the Dry Run output. If you run `turbo run build --dry-run`, for example, the | ||
output will include the combination of all `turbo.json` configurations that were | ||
considered before running the `build` task. | ||
|
||
[1]: /repo/docs/core-concepts/monorepos/running-tasks#running-tasks-from-the-root | ||
[2]: /repo/docs/reference/configuration#pipeline | ||
[3]: /repo/docs/core-concepts/monorepos/running-tasks#specific-workspace-tasks | ||
[4]: https://github.com/vercel/turbo/issues/new/choose | ||
[5]: https://nextjs.org | ||
[6]: https://kit.svelte.dev/ | ||
[7]: /repo/docs/reference/configuration#outputs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9fec98e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
turbo-site – ./docs
turbo.build
turbo.vercel.app
turbo-site.vercel.sh
turbopack.org
www.turborepo.org
turborepo.org
www.turbo.build
turbo.vercel.sh
www.turbopack.org
www.turborepo.com
turbo-site-git-main.vercel.sh