tartup through granular tsBuildInfoFile isolation and TS 6.0's optimized dependency traversal.
- Sweet Spot: The configuration achieves maximum throughput when
composite mode is strictly enforced, --cacheDir is persisted across CI runs, and independent repos are parallelized via workspace tooling.
Core Solution
Start by setting up a root tsconfig.json that defines your monorepo's project structure. Enable composite mode for all sub-projects, and use references to map dependencies between repos:
// root tsconfig.json
{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"incremental": true,
"skipLibCheck": true,
"outDir": "./dist"
},
"references": [
{ "path": "./repos/repo-1" },
{ "path": "./repos/repo-2" },
// ... list all 100 repos here, or use a glob if your workspace manager supports it
]
}
TypeScript 6.0 adds support for glob patterns in references when using the --experimentalGlobbing flag, which is a huge time-saver for 100-repo setups. Add this flag to your build script to auto-discover all repo paths without manual listing.
Step 2: Optimize Individual Repo tsconfig.json
Each of your 100 repos needs a tsconfig.json configured for project references. Key settings for compilation speed:
// repos/repo-X/tsconfig.json
{
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"incremental": true,
"tsBuildInfoFile": "./.tsbuildinfo",
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Avoid include patterns that are too broad, and exclude test files or generated code from compilation if they aren't needed for downstream repos. TypeScript 6.0's incremental builds store more granular build info, so setting tsBuildInfoFile explicitly per repo prevents cache conflicts.
Step 3: Use TypeScript 6.0's New Caching Features
TypeScript 6.0 introduces persistent build caches that survive across clean builds, and improved hash-based change detection for project references. To enable these:
- Set the
--incremental flag globally, and pair it with --tsBuildInfoFile per repo as above
- Use the new
--cacheDir flag to store shared build caches in a central location (e.g., ./node_modules/.cache/ts) that can be persisted across CI runs
- Enable
--experimentalWatchModeOptimizations for local development to reduce file watcher overhead in 100-repo setups
Project references only handle incremental compilation, but you can parallelize independent repo builds using your workspace manager. For example, with Turborepo:
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
}
}
}
This ensures repos are built in dependency order, but independent repos are built in parallel. For 100 repos, this can cut total build time by 40-60% on multi-core machines.
Step 5: Prune Unused Dependencies and References
In a 100-repo monorepo, stale references are a common cause of slow compilation. Use TypeScript 6.0's --listEmittedFiles and --explainFiles flags to identify which files are being included in compilation unnecessarily:
tsc --explainFiles > compilation-report.txt
Remove any unused references entries in root or repo tsconfig.json files, and audit inter-repo dependencies regularly to avoid pulling in unneeded code.
Step 6: Optimize CI Pipelines for Project References
CI builds often reset the environment, wiping incremental caches. To preserve speed in CI:
- Cache the
tsBuildInfoFile and --cacheDir contents across CI runs using your provider's caching (e.g., GitHub Actions cache, CircleCI workspaces)
- Only build repos affected by a PR using your workspace manager's affected command (e.g.,
nx affected --target=build or turbo run build --filter=...[HEAD^1])
- Use TypeScript 6.0's
--noEmitOnError flag to fail fast and avoid wasting time on broken builds
Pitfall Guide
- Disabling
composite Mode for Downstream Dependencies: Turning off composite breaks the contract required for project references. TypeScript relies on pre-compiled .d.ts files to skip type-checking dependency repos; without it, the compiler falls back to full source resolution, negating incremental gains.
- Sharing
tsconfig.json Across Repos Without Isolation Overrides: Inheriting a parent config without explicitly overriding composite, references, and tsBuildInfoFile causes cache collisions and cross-repo type pollution. Each subproject must maintain strict compilation boundaries.
- Overusing
--noUnusedLocals / --noUnusedParameters in CI: These strict linting-equivalent flags force the compiler to traverse and analyze every symbol in the dependency graph. In a 100-repo setup, this adds significant overhead and should be restricted to local IDE linting, not CI compilation.
- Omitting
declaration: true for Dependency Repos: Project references resolve types via generated declaration files. If declaration is false, TypeScript cannot satisfy cross-repo type imports without recompiling source files, triggering cascading rebuilds.
- Neglecting
tsBuildInfoFile Isolation Per Repo: Failing to set explicit tsBuildInfoFile paths causes multiple repos to write to the same cache location. This results in race conditions during parallel builds and invalid incremental caches, forcing full recompilations.
Deliverables
π TypeScript 6.0 Monorepo Optimization Blueprint
A step-by-step architectural guide covering root-level project reference mapping, per-repo tsconfig.json isolation patterns, TS 6.0 persistent caching configuration (--cacheDir, tsBuildInfoFile), and workspace parallelization strategies. Includes decision matrices for choosing between Nx, Turborepo, and pnpm workspaces based on repo count and dependency complexity.
β
Implementation & CI Readiness Checklist