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.
{
"$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:
$ 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.