source: https://turbo.build/repo/docs
build system
tools that performs tasks like minifying, linting, building code.
build system orchestrator
tools that orchestrate the build process. e.g. turborepo, vite.
turborepo is not exactly a mono repo frame work. it orchestrates the build process, so its a build system orchestrator.
monorepo
a monorepo framework provides tools and conventions for managing projects that contain multiple packages or applications within a single repository (monorepo). This includes dependency management between packages, workspace configuration.
e.g., lerna, nx, yarn workspaces, etc.
benefits of turborepo
- remote caching
- parallelisation
- dependency graph awareness
workspace
They are made so that you can share packages in a workspace.
To create a workspace you have to a pnpm-workspace.yml
file and specify the workspaces.
# make docs and everything inside
# packages and app part of workspace.
docs
packages/*
apps/*
Each package / app has a name mentioned in the package.json
.
Package managers uses the name to figure out where to install a package → pnpm add react --filter package-name
. You don’t need to re-install every time your source code changes inside a package - only when you change the locations (or configuration) of your workspace in some way.
It is also the name of the package (for using locally and publishing to npm).
To use a workspace inside another workspace, you need to specify it as a dependency.
{
"dependencies": {
"shared-package": "workspace:*"
}
}
Here, *
means the latest version, which saves us from needing to bump the versions of our dependency if the versions of our packages change. You can use a specific version too.
Tasks
Schema → https://turbo.build/schema.json
In turbo.json
, we can specify tasks to run. cache
property configures caching. Making a task persistent
will allow it to run in the background.
{ "pipeline": { "dev": { "cache": false, "persistent": true } }}
outputs
options takes an array of strings containing paths that are generated as a result of building an application. Turbo uses it to keep track of what to rebuild so that it doesn’t build the same thing again.
If a task depends on other tasks, we can mention it.
{
"pipeline": {
"dev": {
"dependsOn": ["codegen", "db:migrate"],
"cache": false
},
"codegen": {
"outputs": ["./codegen-outputs/**"]
},
"db:migrate": {
"cache": false
}
}
}
Run a task → turbo run <taskname>
Run a task only targeting a specific workspace → turbo run <taskname> --filter <workspace>
Here’s an example of building a next.js app:
{
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**"]
}
}
}
Caching
For every task, you can set cache
property to true or false. By default, turbo will cache a task.
For the caching to work properly, we need to specify the build outputs, otherwise it will only cache terminal outputs. Basically, turbo keeps track of the inputs (your code) and outputs (your build outputs and terminal outputs). If the inputs changes, then only it will re-run a task, otherwise, it will just use the cached results.
--no-cache
→ does not cache the outputs of a task.
--force
→ ignore any cached results, but it will still cache the results.