Task dependencies
Task dependencies allow you to define the execution order of tasks in your project. When running a task, Yarn automatically resolves and executes all required dependencies first, ensuring that prerequisites are met before each task starts.
Defining tasks
Section titled “Defining tasks”Tasks are defined in a taskfile at the root of each workspace. Each task has a name, optional dependencies, and a script to execute:
build: echo "Building the project"
test: build echo "Running tests"In this example, running yarn test will first execute build, then test.
Sequential dependencies
Section titled “Sequential dependencies”By default, dependencies are sequential. Each dependency must complete before the next one starts:
lint: echo "Linting"
typecheck: echo "Type checking"
build: lint typecheck echo "Building"When you run yarn build, the execution order is:
lintruns firsttypecheckruns afterlintcompletesbuildruns aftertypecheckcompletes
This creates a strict ordering where each task waits for the previous one to finish.
Parallel dependencies
Section titled “Parallel dependencies”To run dependencies in parallel, add the & suffix to the dependency name:
lint: echo "Linting"
typecheck: echo "Type checking"
build: lint& typecheck& echo "Building"Now when you run yarn build:
lintandtypecheckrun simultaneouslybuildruns after both complete
Parallel execution can significantly speed up your build pipeline when tasks are independent of each other.
Mixing sequential and parallel dependencies
Section titled “Mixing sequential and parallel dependencies”You can combine sequential and parallel dependencies in a single task definition. Tasks with & form parallel groups, while tasks without & create sequential barriers:
a: echo "Task A"
b: echo "Task B"
c: echo "Task C"
d: echo "Task D"
e: a b& c& d echo "Task E"The execution order for yarn e is:
aruns first (sequential barrier)bandcrun in parallel (both have&)druns afterbandccomplete (sequential barrier)eruns afterdcompletes
This pattern is useful when you have a setup task that must run first, followed by independent tasks that can run in parallel, and finally tasks that need all previous work to be done.
Cross-workspace dependencies
Section titled “Cross-workspace dependencies”Tasks can depend on tasks from other workspaces that are listed as dependencies in your package.json. Use the workspace:task syntax:
# In packages/app/taskfilebuild: pkg-utils:build pkg-core:build echo "Building app"This ensures that both pkg-utils and pkg-core are built before app. Note that pkg-utils and pkg-core must be declared as dependencies (or devDependencies) of app in its package.json.
You can also use glob patterns to match multiple dependency workspaces:
# Depend on all dependency packages matching the patternbuild: @my-scope/*:build echo "Building after all @my-scope packages"The glob pattern only matches workspaces that are both:
- Listed as dependencies of the current workspace
- Match the glob pattern
This ensures that task dependencies follow the same dependency graph as your packages, preventing accidental coupling between unrelated workspaces.
Parallel cross-workspace dependencies
Section titled “Parallel cross-workspace dependencies”Cross-workspace dependencies also support the parallel & modifier:
# In packages/app/taskfilebuild: pkg-utils:build& pkg-core:build& echo "Building app"Now pkg-utils:build and pkg-core:build run in parallel before app:build.
You can mix local and cross-workspace dependencies with any combination of sequential and parallel:
build: setup pkg-utils:build& pkg-core:build& finalize echo "Building app"Execution order:
setupruns firstpkg-utils:buildandpkg-core:buildrun in parallelfinalizeruns after both completebuildruns last
Transitive dependencies
Section titled “Transitive dependencies”Yarn automatically resolves transitive dependencies. If task A depends on B, and B depends on C, running A will execute C, then B, then A:
build: echo "Building pkg-a"
# packages/pkg-b/taskfilebuild: pkg-a:build echo "Building pkg-b"
# packages/pkg-c/taskfilebuild: pkg-b:build echo "Building pkg-c"Running yarn build in pkg-c will:
- Execute
pkg-a:buildfirst (no dependencies) - Execute
pkg-b:buildafterpkg-acompletes - Execute
pkg-c:buildafterpkg-bcompletes
The dependency resolution computes the full transitive closure, so pkg-c:build knows it must wait for both pkg-a:build and pkg-b:build.
Including tasks from other workspaces
Section titled “Including tasks from other workspaces”You can include task definitions from dependency workspaces using the include directive. This allows you to reuse common task definitions across multiple workspaces without duplicating them.
Basic include
Section titled “Basic include”To include all tasks from a dependency workspace’s taskfile:
include pkg-utils
build: lint echo "Building"This imports all tasks defined in pkg-utils’s taskfile into the current workspace. If pkg-utils has a lint task, it becomes available as if it were defined locally.
Include with custom path
Section titled “Include with custom path”By default, include loads the taskfile at the root of the target workspace. You can specify a custom path:
include pkg-utils/tasks/common.tasks
build: lint typecheck echo "Building"This loads tasks from tasks/common.tasks within the pkg-utils workspace instead of the default taskfile.
Scoped package includes
Section titled “Scoped package includes”Scoped packages are fully supported:
include @my-scope/my-lib
build: lint echo "Building"You can also specify a custom path for scoped packages:
include @my-scope/my-lib/tasks/shared.tasksInclude requirements
Section titled “Include requirements”The include target must be declared as a dependency (or devDependency) in your package.json. This ensures that task includes follow the same dependency graph as your packages:
{ "name": "my-app", "dependencies": { "pkg-utils": "workspace:*" }}If you try to include a workspace that isn’t a dependency, you’ll get an error:
Error: Cannot include 'pkg-other' from 'my-app': not listed as a dependencyTask precedence
Section titled “Task precedence”When including tasks, local task definitions take precedence over included ones. If both your taskfile and an included taskfile define the same task name, your local definition is used:
include pkg-utils
# This overrides any 'build' task from pkg-utilsbuild: echo "Custom build"Multiple includes
Section titled “Multiple includes”You can include from multiple workspaces:
include pkg-utilsinclude pkg-core
build: lint typecheck test echo "Building"Tasks from earlier includes take precedence over later ones if there are naming conflicts.
Cycle detection
Section titled “Cycle detection”Yarn detects circular dependencies and reports an error:
# This will fail!a: b echo "A"
b: c echo "B"
c: a echo "C"Running any of these tasks will result in an error indicating the cycle: a -> b -> c -> a.