diff --git a/docs/pages/docs/core-concepts/filtering.mdx b/docs/pages/docs/core-concepts/filtering.mdx index 7adb021a35ffe..f0685d29375e0 100644 --- a/docs/pages/docs/core-concepts/filtering.mdx +++ b/docs/pages/docs/core-concepts/filtering.mdx @@ -11,7 +11,7 @@ import HeartIcon from "@heroicons/react/solid/HeartIcon"; Filtering packages allows you to target your tasks to only the packages you care about. Turborepo supports a `pnpm`-like `--filter` flag that allows you to select the packages that will act as "entry points" into your monorepo's package/task graph. -You can filter packages by name, directory, include dependents/dependencies, and by changes +You can filter your project by package name, package directory, whether packages include dependents/dependencies, and by changes in git history. `turbo` will run each task against each matched package, ensuring that any dependencies @@ -34,7 +34,7 @@ Supports exact matches (`--filter=my-pkg`), and globs (`--filter=*my-pkg*`) are Scoped packages (`@foo/bar`) can be abbreviated to just the package name (`bar`) as long as the package name is unique within the monorepo (e.g. `@foo/bar` exists, but `@baz/bar` does not). -The root package can be selected using the token `//`. +The monorepo's root package can be selected using the token `//`. ```sh # Build 'my-pkg', letting turbo infer task dependencies from the pipeline defined in turbo.json diff --git a/docs/pages/docs/core-concepts/meta.json b/docs/pages/docs/core-concepts/meta.json index 0a12c1d07d671..92e2255b6656c 100644 --- a/docs/pages/docs/core-concepts/meta.json +++ b/docs/pages/docs/core-concepts/meta.json @@ -1,4 +1,5 @@ { + "workspaces": "Workspaces", "pipelines": "Pipelines", "filtering": "Filtering Packages", "caching": "Caching", diff --git a/docs/pages/docs/core-concepts/pipelines.mdx b/docs/pages/docs/core-concepts/pipelines.mdx index a21db26c2df70..508c1144b6147 100644 --- a/docs/pages/docs/core-concepts/pipelines.mdx +++ b/docs/pages/docs/core-concepts/pipelines.mdx @@ -23,7 +23,7 @@ Notice that `turbo` is able to schedule tasks efficiently--collapsing waterfalls ## Defining a `pipeline` -To define your project's task dependency graph, use the [`pipeline`](../reference/configuration#pipeline) key in the `turbo.json` configuration file at the root of your project. `turbo` interprets this configuration and conventions to properly schedule, execute, and cache the outputs of the tasks in your project. +To define your monorepo's task dependency graph, use the [`pipeline`](../reference/configuration#pipeline) key in the `turbo.json` configuration file at the root of your monorepo. `turbo` interprets this configuration and conventions to properly schedule, execute, and cache the outputs of the tasks in your monorepo. Each key in the [`pipeline`](../reference/configuration#pipeline) object is the name of a task that can be executed by [`turbo run`](../reference/command-line-reference#turbo-run-task1-task2-1). You can specify its dependencies with the [`dependsOn`](../reference/configuration#dependson) key beneath it as well as some other options related to [caching](./caching). @@ -222,12 +222,12 @@ This seems like it goes against the `"test": { "dependsOn": ["build"] }` and `"d [`outputs`](../reference/configuration#outputs) at the moment.** -### Running tasks defined in the root `package.json` +### Running tasks defined in the monorepo's root `package.json` file `turbo` can run tasks that exist in the `package.json` file at the root of the monorepo. These must be added to the pipeline configuration using the form `"//#": {...}`. This is true even for tasks that already have their own entry. For example, if you already have `"build": {...}` -in your pipeline, but want to include the `build` script defined in the root `package.json` when running +in your pipeline, but want to include the `build` script defined in the monorepo's root `package.json` file when running `turbo run build`, you must opt the root into it by also including `"//#build": {...}` in your configuration. Conversely, you _do not_ need to define a generic `"my-task": {...}` entry if all you need is `"//#my-task": {...}`. @@ -263,9 +263,9 @@ A sample pipeline that defines the root task `format` and opts the root into `te } ``` -**A note on recursion**: Scripts defined in the root `package.json` often call `turbo` themselves. +**A note on recursion**: Scripts defined in the monorepo's root `package.json` often call `turbo` themselves. For example, the `build` script might be `turbo run build`. In this situation, including `//#build` in -`turbo run build` will cause infinite recursion. It is for this reason that tasks run from the root must +`turbo run build` will cause infinite recursion. It is for this reason that tasks run from the monorepo's root must be explicitly opted into via including `//#` in the pipeline configuration. `turbo` includes some best-effort checking to produce an error in the recursion situations, but it is up to you to to only opt in those tasks which don't themselves trigger a `turbo` run that would recurse. diff --git a/docs/pages/docs/core-concepts/workspaces.mdx b/docs/pages/docs/core-concepts/workspaces.mdx new file mode 100644 index 0000000000000..b0ad77f7bcdbd --- /dev/null +++ b/docs/pages/docs/core-concepts/workspaces.mdx @@ -0,0 +1,201 @@ +--- +title: Workspaces +description: Use workspaces to organize your turborepo apps and packages. +--- + +import Callout from "../../../components/callout"; +import HeartIcon from "@heroicons/react/solid/HeartIcon"; +import { Tabs, Tab } from '../../../components/Tabs' + +# Getting started with workspaces + +Workspaces are a feature implemented by package managers to assist with working on multiple apps and packages in the same codebase. + +Turborepo is compatible with three package managers, [npm](https://docs.npmjs.com/cli/v8/using-npm/workspaces#description), [Yarn](https://classic.yarnpkg.com/lang/en/docs/workspaces/), and [pnpm](https://pnpm.io/workspaces), each with its own implementation of workspaces and functionality. Your package manager will determine how your apps and packages are organized in your workspaces and run in your turborepo. + +## Configuring workspaces + +To use workspaces, you'll first need to declare their file system locations to your package manager + +A common/recommended convention is to have an `apps` folder and a `packages` folder. The `apps` folder can contain workspaces for launchable apps, such as a Next.js or Svelte app. The `packages` folder can contain workspaces for packages that are used by either an app, or another package. Again, this isn't a requirement, but just a suggested folder structure + + +Unlike when working in a single-package repository, you'll need to consider how to name your workspaces. If you avoid npm naming collisions, you can use an npm organization or user scope to namespace your packages. For example, you might set the `name` key in `./apps/api/package.json` to `@mycompany/api`. + + + + + + Add the folders you want to configure as workspaces to the `workspaces` field in your root `package.json` file. This field contains a list of workspace folders in the form of globs: + + ```json + { + "name": "monorepo", + "version": "1.0.0", + "workspaces": [ + "docs", + "apps/*", + "packages/*" + ] + } + ``` + + + + + Add the folders you want to configure as workspaces to the `workspaces` field in the root `package.json` file. This field contains a list of workspace folders in the form of globs: + + ```json + { + "name": "monorepo", + "version": "1.0.0", + "workspaces": [ + "docs", + "apps/*", + "packages/*" + ] + } + ``` + + + + + + Add the folders you want to configure as workspaces to the `pnpm-workspace.yaml` file that exists in your root directory. This file contains a list of workspace folders in the form of globs: + + ```yaml + packages: + - "docs" + - "apps/*" + - "packages/*" + ``` + + + + +Each folder that matches any of the globs in the list is considered a workspace folder. In the examples, the `apps` and `packages` folders contain folders that are workspaces, and the `docs` folder itself is a workspace. + +``` +monorepo/ +├─ docs/ +├─ apps/ +│ ├─ api/ +│ ├─ mobile/ +├─ packages/ +│ ├─ tsconfig/ +│ ├─ config/ +├─ sdk/ +``` + +Using the same workspace configuration, the `monorepo/docs/`, `monorepo/apps/api/`, `monorepo/apps/mobile/`, `monorepo/packages/config/`, and `monorepo/packages/tsconfig/` folders are all considered workspaces. +The `monorepo/sdk/` folder is not considered a workspace and it is not included in the workspace configuration. + +## Managing workspaces + +When you move, delete, or rename your workspaces, you will have to make sure that all folders linked within your `package.json` matches. Anytime you change the configuration of your workspace, make sure all the dependencies of the workspace are also updated. Re-run your npm client's install command to check your configuration. If there are any problems after that, you may have to delete your `node_modules` folder and run an install again. + +## Managing dependencies + +To manage dependencies within workspaces in your monorepo, you will need to run commands that will only manage the dependencies of each workspace rather than for the entire monorepo. + + + + + **Install** + ```bash + npm install -w= + ``` + + Example: + ```bash + npm install react -w=web + ``` + + **Uninstall** + ```bash + npm uninstall -w= + ``` + + Example: + ```bash + npm uninstall react -w=web + ``` + + **Update** + ```bash + npm update -w= + ``` + + Example: + ```bash + npm update react -w=web + ``` + + + + + **Install** + ```bash + yarn workspace add + ``` + + Example: + ```bash + yarn workspace web add react + ``` + + **Uninstall** + ```bash + yarn workspace remove + ``` + + Example: + ```bash + yarn workspace web remove react + ``` + + **Update** + ```bash + yarn workspace upgrade + ``` + + Example: + ```bash + yarn workspace web upgrade react + ``` + + + + + **Install** + ```bash + pnpm add --filter + ``` + + Example: + ```bash + pnpm add react --filter web + ``` + + **Uninstall** + ```bash + pnpm uninstall --filter + ``` + + Example: + ```bash + pnpm uninstall react --filter web + ``` + + **Update** + ```bash + pnpm up --filter + ``` + + Example: + ```bash + pnpm up react --filter web + ``` + + + diff --git a/docs/pages/docs/getting-started.mdx b/docs/pages/docs/getting-started.mdx index f41de3bf4f871..09fa5d8b38a7d 100644 --- a/docs/pages/docs/getting-started.mdx +++ b/docs/pages/docs/getting-started.mdx @@ -1,5 +1,5 @@ --- -title: Getting Started +title: Getting Started with Turborepo description: Create your first monorepo or add Turborepo to an existing project. --- @@ -7,25 +7,21 @@ import Callout from "../../components/callout"; import Beta from "../../components/beta"; import { Tabs, Tab } from '../../components/Tabs' -# Getting Started with Turborepo +# Overview -## Clone an example or starter monorepo +Turborepo is a build system for JavaScript and TypeScript monorepos: codebases containing multiple projects, often using multiple frameworks, in a single unified code repository. Monorepos have many advantages, but they require appropriate tooling in order to scale. Turborepo leverages advanced build system ideas and techniques to speed up development, without the configuration and complexity. By abstracting the configurations, scripts, and tooling, Turborepo allows you to start shipping fast. -If you're starting a brand new monorepo, you can get started with a single command. +You can incrementally adopt Turborepo for new and existing projects. To create a new monorepo, get started with: ```sh npx create-turbo@latest ``` -Follow the prompts to bootstrap a brand new Turborepo. - -To see more examples and starters, have a look at the [examples directory on GitHub](https://github.com/vercel/turborepo/blob/main/examples) +You can also clone a Turborepo starter repository to get a head start on your monorepo. To see Turborepo examples and starters, see the [Turborepo examples directory on GitHub](https://github.com/vercel/turborepo/tree/main/examples). ## Add Turborepo to your existing monorepo -Turborepo was designed to be incrementally adopted. Adding it to an existing monorepo takes only a few minutes. - -Turborepo works with [Yarn v1](https://classic.yarnpkg.com/lang/en/), [npm](https://npmjs.com), and [pnpm](https://pnpm.io/) workspaces. The `turbo` CLI works on the following operating systems. +`turbo` works with [Yarn](https://classic.yarnpkg.com/lang/en/), [npm](https://npmjs.com), and [pnpm](https://pnpm.io/) on the following operating systems: - macOS darwin 64-bit (Intel), ARM 64-bit (Apple Silicon) - Linux 32-bit, 64-bit, ARM, ARM 64-bit, MIPS 64-bit Little Endian, PowerPC 64-bit Little Endian, IBM Z 64-bit Big Endian @@ -34,9 +30,61 @@ Turborepo works with [Yarn v1](https://classic.yarnpkg.com/lang/en/), [npm](http - NetBSD AMD64 - Android ARM 64-bit -### Install `turbo` +## Configure workspaces + +`turbo` is built on top of Workspaces, a way of managing multiple packages from within a single monorepo package. Turborepo is compatible with the workspace implementations from all package managers. For more information on managing your Turborepo workspaces, see the [Workspaces](./core-concepts/workspaces) documentation. + +You can configure workspaces any way you want, but a common folder structure example is keeping applications in the `/apps` folder and packages in the `/packages` folder. The configuration of these folders is different for each package manager. + + + +
+Specify your `workspaces` in your monorepo's root `package.json` file: + +```json filename="package.json" +{ + "workspaces": [ + "packages/*", + "apps/*" + ] +} +``` + + + +
+Specify your `workspaces` in your monorepo's root `package.json` file: + +```json filename="package.json" +{ + "workspaces": [ + "packages/*", + "apps/*" + ] +} +``` + + + +
+Specify your `packages` in `pnpm-workspaces.yaml`. +```yaml filename="pnpm-workspace.yaml" +packages: + - "packages/*" + - "apps/*" +``` + + + +After configuring your workspaces, re-run your package manager's `install` command. + + + Note: Nested workspaces are not supported. As package names are required to be unique, moving each package to be a child of the monorepo's root package should meet your needs. + + +## Install `turbo` -Add `turbo` as a development dependency in the root of your project. +Add `turbo` as a development dependency in the root of your monorepo. @@ -56,70 +104,92 @@ Add `turbo` as a development dependency in the root of your project. -The `turbo` package is a little shell that will install the proper `@turborepo/*` packages. +The `turbo` package is a little shell that will install the proper `turbo--` package for you operating system and architecture. -### Create `turbo.json` +## Create `turbo.json` -In your root directory, create an empty file named `turbo.json`. -This will hold the configuration for Turborepo in your project. -If your git repo's base branch is NOT `origin/master` then you need to specify a `baseBranch` too (for example, ours is set to `origin/main`). +In the root of your monorepo, create an empty file named `turbo.json`. This will hold the configuration for Turborepo. -```json +If your git repo's base branch is not `origin/master`, then you need to specify a `baseBranch` too. For example, `origin/main`. + +```json filename="./turbo.json" { "$schema": "https://turborepo.org/schema.json", "baseBranch": "origin/main" } ``` -### Create a `pipeline` +## Create a `pipeline` + +To define your monorepo's task dependency graph, use the [`pipeline`](./features/pipelines) key in the `turbo.json` configuration file at the root of monorepo. `turbo` interprets this configuration to optimally schedule, execute, and cache the outputs of each of the `package.json` scripts defined in your workspaces. -In `turbo.json`, add the commands you want to "turbocharge" to your pipeline. +Each key in the [`pipeline`](./features/pipelines) object is the name of a `package.json` script that can be executed by [`turbo run`](./reference/command-line-reference#turbo-run-task1-task2-1). You can specify its dependencies with the [`dependsOn`](../reference/configuration#dependson) key beneath it as well as some other options related to [caching](./features/caching). For more information on configuring your pipeline, see the [`Pipelines`](./core-concepts/pipelines) documentation. -Your pipeline both defines the way in which your npm `package.json` scripts relate to each other, and configures cache artifacts for those scripts. These relationships and cache settings are then fanned out and applied to all package tasks across your entire monorepo. +Packages that do not have the specified script defined in their `package.json`'s list of `scripts` will be ignored by `turbo`. -```jsonc +```jsonc filename="./turbo.json" { "$schema": "https://turborepo.org/schema.json", - "baseBranch": "origin/main", "pipeline": { "build": { + // A package's `build` script depends on that package's + // dependencies' and devDependencies' + // `build` tasks being completed first + // (the `^` symbol signifies `upstream`). "dependsOn": ["^build"], // note: output globs are relative to each package's `package.json` // (and not the monorepo root) "outputs": [".next/**"] }, "test": { - "dependsOn": ["^build"], - "outputs": [] + // A package's `test` script depends on that package's + // own `build` script being completed first. + "dependsOn": ["build"], + "outputs": [], + // A package's `test` script should only be rerun when + // either a `.tsx` or `.ts` file has changed in `src` or `test` folders. + "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"] }, "lint": { + // A package's `lint` script has no dependencies and + // can be run whenever. It also has no filesystem outputs. "outputs": [] }, - "dev": { - "cache": false + "deploy": { + // A package's `deploy` script depends on the `build`, + // `test`, and `lint` scripts of the same package + // being completed. It also has no filesystem outputs. + "dependsOn": ["build", "test", "lint"], + "outputs": [] } } } ``` -In the above example, the `build` and `test` tasks are dependent on their packages `dependencies` and `devDependencies` being built first, this is denoted with the `^` prefix. +The rough execution order for a given package based on the `dependsOn` keys: + +1. `build` once its upstream dependencies have run their `build` commands +2. `test` once its _own_ `build` command is finished and has no filesystem outputs (just logs) within a package +3. `lint` runs in an arbitrary order as it has no upstream dependencies +4. `deploy` once its _own_ `build`, `test`, and `lint` commands have finished. -For each script in each workspace's `package.json`, Turborepo will cache files outputted to `dist/**` and `build/**` folders relative to each packages's `package.json` by default if an override isn't added. Using the [`outputs`](./core-concepts/caching#configuring-cache-outputs-1) array allows you to override the default cache folders, -like in the example above, where the `.next/**` folder is selected to be the default cache outputs folder for the `build` task for each package. Turborepo will automatically record and cache logs to `.turbo/turbo-