Task Orchestration

Task Orchestration Across Packages

npm 2,036 run build --workspaces runs the members in npm's order, and runs all of them every time. A task runner reads the dependency graph instead, orders the work, and skips anything whose inputs have not changed. Turborepo 226,392 (github.com/vercel/turborepo (https://github.com/vercel/turborepo 31,149 ), MIT, 2.10.13) is the smallest step up.

turbo.json: build dependencies first, test after buildJSON
{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
    "test": { "dependsOn": ["build"] }
  }
}

^build means "the build task of every package I depend on"; without the caret it means this package's own task. outputs tells Turborepo which files to save so it can restore them on a cache hit. Run it twice:

Output of 124
$ npx turbo run build
@shop/core:build: cache miss, executing dcd772a3f2d937e2
@shop/cli:build: cache miss, executing c3fd403196fcafac
 Tasks: 2 successful, 2 total   Time: 987ms
$ npx turbo run build
@shop/core:build: cache hit, replaying logs dcd772a3f2d937e2
 Tasks: 2 successful, 2 total   Time: 22ms >>> FULL TURBO

The hash covers the package's sources, its dependencies' hashes, the task definition and any environment variables you declare in env. Declare them: a task that reads process.env.API_URL without listing it will happily replay a cache entry built against the wrong value.

Choosing an orchestrator, with Nx 23.2.1 180,159 as the heavyweight option
npm run --workspaces Turborepo Nx
Topological order No Yes Yes
Local + remote cache No Yes Yes
Extra install None 1 binary Plugin set
Best for 2-3 packages Any size Large, generated code