TypeScript
Project structure
Learn performance with project references.
Performance with project references
Project references split a large project into smaller, independently compiled sub-projects. Only the changed sub-project and its dependents are recompiled; this significantly reduces compile time in large codebases. Each sub-project has composite: true and its own .tsbuildinfo cache.
// app → core → utils
// if utils changes: utils + core + app
// if app changes: only app
Build mode resolves the dependency order automatically.
Incremental cache
Each sub-project writes the previous build's type graph to a .tsbuildinfo file. On the next build, only changed files and the types they affect are re-resolved. This saves minutes instead of seconds in large projects.
// core/.tsbuildinfo
// type graph of the last build
If the cache is deleted, a full rebuild occurs.
Exercise Compute the rebuild scope
Write a computeRebuildScope function taking changed projects and a reverse dependency map. Collect the changed project and its dependents into a set and return a sorted array. When core changes and core → app is a dependency, produce the output app, core.
Show example solution
function computeRebuildScope(changed: string[], reverseDeps: Record<string, string[]>): string[] {
const rebuild = new Set<string>(changed);
for (const file of changed) {
for (const dependent of reverseDeps[file] || []) {
rebuild.add(dependent);
}
}
return Array.from(rebuild).sort();
}
const changed = ["core"];
const reverseDeps = { core: ["app"], utils: ["core"] };
console.log(computeRebuildScope(changed, reverseDeps).join(", "));
Test yourself
-
How do project references improve build time?
- They disable type checking entirely
- They reduce bundle size
- They recompile only changed and dependent projects
- They remove the need for a tsconfig file
Show answer
They recompile only changed and dependent projects — References provide incremental builds by recompiling the changed project and its dependents; type checking is not disabled, bundle size is unchanged, and tsconfig is still required.
-
Incremental flag
{
"compilerOptions": {
"composite": true,
"____": true
}
}
Show answer
{
"compilerOptions": {
"composite": true,
"incremental": true
}
}
-
Structure parts
- Project references
- splits project into sub-projects
- .tsbuildinfo
- type graph cache
- composite: true
- enables referenceability
- Build modu
- resolves dependency order
Next lesson: Summary - Performance