- We need to install Turborepo in our project by running
npm install turbo -D
to install it in the root of our project as adevDependency
. - Then, we need to update
.gitignore
to preventgit
to include certain folders in version control. In this case, we're going to ignore.turbo
and the output folders for all the applications in the monorepo,dist/**
and.next/**
- Create a
turbo.json
file and reference the Turborepo's JSON Schema
- Let's add the
pipeline
object in theturbo.json
file. - Select the scripts we want Turborepo to take care of from our
package.json
file, then. For instance, if we want Turborepo to run thedev
command, we have to create a"dev"
key inside the"pipeline"
object inturbo.json
. - We can try this out with the Turborepo CLI, we just need to run
npx turbo run [your pipeline name]
- Make sure we add the
@monorepo/utils
package as a dependency in the@monorepo/blog
and@monorepo/dashboard
projects to avoid any dependency problems. For this we can use the commandnpm install @monorepo/utils -w=@monorepo/blog -w=@monorepo/dashboard
. For more information, see this Egghead.io lesson Install dependencies for specific packages in a monorepo - We migrate all the commands that we care about as Turborepo pipelines.
-
dev
->npx turbo run dev
-
check
->npx turbo run test typecheck
-
test
->npx turbo run test
-
build
->npx turbo run build
-
typecheck
->npx turbo run typecheck
- Let's replace all the scripts we have in the root
package.json
with their turborepo counterparts.
In some cases, you want to make sure that Turborepo is building the dependencies in a specific order, for example, we always want to build the @monorepo/utils
first, before building the @monorepo/dashboard
and @monorepo/blog
projects. For that, we have to add the "dependsOn"
key to the pipeline we want to behave like that.
"build": {
+ "dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
In some other cases where you need more granular control over what to build first in different projects you can do the following:
Turborepo is already taking care of building things in the right order because @monorep/utils
is a dependency of @monorepo/dashboard
and @monorepo/blog
and that we're already specifying that @monorepo/dashboard
and @monorepo/blog
depend on the build step from @monorepo/utils
to succeed. All that said, for this lesson we're going to remove the @monorepo/utils
dependencies from @monorepo/dashboard
and @monorepo/blog
, then we delete the build artifacts from @monorepo/utils
(the dist
folder), and finally we'll run npm install
. Once that's done we're going to run npm run build
and we'll see that we have a problem with our build because we're building things "out of sync", that means that there's no way for Turborepo to tell which project to build first since we don't specify that @monorepo/utils
is a dependency of @monorepo/blog
and @monorepo/dashboard
.
The way to fix this would be to define a pipeline for both projects @monorepo/dashboard
and @monorepo/blog
.
With this we're telling Turborepo to always run the @monorepo/utils
project, before running the build command in @monorepo/dashboard
and @monorepo/blog
In the package.json
file of @monorepo/dashboard
and @monorepo/blog
All the patch for this lesson can be found in the /patches/lesson-03.patch
file.
"dependencies": {
- "@monorepo/utils": "^1.0.0",
In turbo.json
"pipeline": {
+ "@monorepo/dashboard#build": {
+ "dependsOn": ["@monorepo/utils#build"]
+ },
+ "@monorepo/blog#build": {
+ "dependsOn": ["@monorepo/utils#build"]
+ },
For this we need to install Graphviz first. Once we have that installed, we can run npx turbo run [pipeline to inspect] --graph=name-of-the-graph.{svg|jpg|json|pdf|png|html}
and it will generate the file you specified for you. I found this to be useful to understand how your projects depend on each other.
We already have a few npm scripts that are not using Turborepo, instead they are using raw npm scripts, like npm run typecheck -w @monorepo/dashboard
.
In order to tell Turborepo to run just in certain projects, we need to use the --filter
flag.
Official --filter
documentation
To test out the filters we will use the patch that's in patches/lesson-05-filter-command.patch
, lets:
git checkout -b lesson-5
You can name your branch whatever you want.git apply patches/lesson-05-filter-command.patch
- Start filtering out
- By package
- By dependants
- By dependencies
- Exclude
- Git changed packages
Now, let's update the npm scripts we have in our root package.json
file
Turborepo will terminate the process it's running if it encounters an error, we can prevent this from happening if we pass the --continue=true
flag to the Turborepo command we want to execute.
npx turbo run test --continue=true
- Make the tests in
utils/
to fail - Run
npx turbo run test
- See what happens
- Add the
--continue=true
flag to thenpx turbo run test
command
I have found this to be useful when I want to know the impact of my changes across the whole project. Given the fact that @monorepo/utils
is a dependency of @monorepo/dashboard
and @monorepo/blog
it's important to know the impact of my changes not only in the @monorepo/utils
package, but in the packages that use it.
We can bypass Turborepo's local (and remote) cache if we need to. This will run the command you specify like it was the first time you run it. I have found this useful in development mode and when I'm trying to debug something inside a package and I want to be 100% sure that I'm getting the latest version of my changes.
npx turbo run test --force
You can also clear your local cache by deleting the node_modules/.cache/turbo
folder.
rm -rf node_modules/.cache/.turbo
One strategy that I've found useful is to use the graph generated by the --graph
command, plus, the --dry
command. It will give you a nice output telling you what's going on whenever you run the command. Let's take the build
command as an example
npx turbo run build --dry=json
And it will give you a nice JSON output, I'd pay special attention to the packages
, dependencies
, and dependents
keys.
{
"packages": ["@monorepo/blog", "@monorepo/dashboard", "@monorepo/utils"],
"tasks": [
{
"taskId": "@monorepo/utils#build",
"task": "build",
"package": "@monorepo/utils",
"hash": "998cbe802d4e6ec4",
"command": "tsup",
"outputs": [".next/**", "dist/**"],
"logFile": "libs/utils/.turbo/turbo-build.log",
"directory": "libs/utils",
"dependencies": [],
"dependents": ["@monorepo/blog#build", "@monorepo/dashboard#build"]
},
{
"taskId": "@monorepo/blog#build",
"task": "build",
"package": "@monorepo/blog",
"hash": "e9f89b69796ea268",
"command": "next build",
"outputs": [".next/**", "dist/**"],
"logFile": "apps/blog/.turbo/turbo-build.log",
"directory": "apps/blog",
"dependencies": ["@monorepo/utils#build"],
"dependents": []
},
{
"taskId": "@monorepo/dashboard#build",
"task": "build",
"package": "@monorepo/dashboard",
"hash": "2c8a4a51bbd1fb7d",
"command": "tsc \u0026\u0026 vite build",
"outputs": [".next/**", "dist/**"],
"logFile": "apps/dashboard/.turbo/turbo-build.log",
"directory": "apps/dashboard",
"dependencies": ["@monorepo/utils#build"],
"dependents": []
}
]
}
I've found this useful specially in CI, there I just want to see the logs of the packages that have changed instead of the logs for everything. We can choose the level of detail of our logs by passing a value to the --output-logs
flag, it could either be full
or new-only
npx turbo run build --output-logs=new-only
So far, our cache only works locally - it lives inside node_modules/.cache/turbo
, and that means that we can't share the cache between machines. The problem that remote caching solves is exactly that, being able to share the cache between machines.
npx turbo login
npx turbo link
Let's run npx turbo run test
, delete the turbo cache directory rm -rf node_modules/.cache/turbo
and then let's run npx turbo run test
, you'll see that we're getting the cached version from Turborepo's Remote Cache that's hosted on Vercel.
You can even take a look at your usage in this tab in your Vercel dashboard. https://vercel.com/dashboard/usage
Another way to test that remote caching is working is to use the --remote-only
flag to ignore the local cache.