Declare outputs to cache

No outputs key means a cache hit restores logs but no files.

Turborepo docsturborepo.dev
Turborepo's core principle: never do the same work twice.
CachingRead docs ↗

From turborepo, caching/RULE.md and gotchas.md.

A hit with nothing in it

Build, wipe dist/ like a fresh checkout, build again.

No outputsBad
    "build": { "dependsOn": ["^build"] }
    outputs declaredGood
      "outputs": ["dist/**"]
      {
        "tasks": {
          "build": {
            "dependsOn": ["^build"],
            // Next.js: cache the build, not its own cache or dev files
            "outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
          },
          "lint": { "outputs": [] }   // stdout only: nothing to restore
        }
      }

      Never cache a deploy

      Deploy, roll prod back, then deploy the same commit again.

      Cached deployBad
      Productionv1
      "deploy": { "dependsOn": ["build"] }
      cache: falseGood
      Productionv1
      "deploy": { "dependsOn": ["build"], "cache": false }

      Why it matters, pros and cons

      Why it matters

      The cache stores the files matched by outputs plus the logs. Without the key, a hit replays text and restores nothing.

      Pros

      • A hit rebuilds dist/ in milliseconds.
      • Fresh CI checkouts get the files too.
      • Excluding .next/cache keeps archives small.

      Cons

      • Globs must match where the tool really writes.
      • tsc --noEmit with incremental still writes .tsbuildinfo.
      • Side-effect tasks must opt out with cache: false.