Depend on packages by name
A workspace:* dependency is the edge turbo orders and hashes by.
From turborepo, best-practices/packages.md.
Reach-in import vs dependency
Everything is cached. Edit ui and build.
Relative importBad
apps/web/app/page.tsximport { Button } from
"../../packages/ui/src/button"
web sees ui v10 stale hits
apps/web deps: { "next": "…" }Declared dependencyGood
apps/web/app/page.tsximport { Button } from
"@repo/ui/button"
web sees ui v10 stale hits
"@repo/ui": "workspace:*"// packages/ui/package.json
{
"name": "@repo/ui",
"exports": { "./button": "./src/button.tsx" } // JIT: the app's bundler compiles it
}
// apps/web/package.json (npm/yarn use "*")
{ "dependencies": { "@repo/ui": "workspace:*" } }
// apps/web/app/page.tsx
import { Button } from "@repo/ui/button";
Why it matters, pros and cons
Why it matters
Turbo builds its graph from package.json dependencies. An import it can't see adds no edge, so no order and no invalidation.
Pros
^buildorders the build.- A
uiedit bustsweb's cache. --affectedandturbo prunefollow it.
Cons
- A JIT package has no build of its own to cache.
- A compiled package needs
dist/**inoutputs. - No
prebuildthat cds into other packages.