Skip to content

perf(@angular/build): share sass directory and resolution caches across stylesheets - #34041

Merged
alan-agius4 merged 3 commits into
angular:mainfrom
alan-agius4:perf/sass-caching
Sep 9, 2026
Merged

perf(@angular/build): share sass directory and resolution caches across stylesheets#34041
alan-agius4 merged 3 commits into
angular:mainfrom
alan-agius4:perf/sass-caching

Conversation

@alan-agius4

Copy link
Copy Markdown
Collaborator

Previously, Sass resolution caches (resolutionCache and packageRootCache) in sass-language.ts and the filesystem directory entry cache (directoryCache) in sass-service.ts were created anew for every individual stylesheet compilation request.

When compiling applications that use component styles importing shared design tokens or library stylesheets (such as @angular/material or deep-imported @material/* packages), rebasing importers repeatedly invoked synchronous fs.readdirSync across the same node module package directories, and re-executed esbuild resolution calls.

To eliminate redundant disk I/O and resolution overhead:

  • Hoist directoryCache to an instance property of SassCompiler, persisting directory listings across compile calls and clearing them upon compiler shutdown in close().
  • Hoist resolutionCache and packageRootCache to module-scoped caches in sass-language.ts, clearing them during shutdownSassWorkerPool().
  • Contextualize relative import resolution cache keys using the containing URL to preserve correctness while allowing package specifiers to resolve once across all stylesheets.

In benchmarks on an application with 50 component SCSS stylesheets importing @angular/material, synchronous fs.readdirSync calls dropped from 2,900 to 205 (-92.9%), build.resolve calls dropped from 100 to 2 (-98.0%), and compilation time improved by up to 26.4%.

@angular-robot angular-robot Bot added area: performance Issues related to performance area: @angular/build labels Sep 8, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces persistent caching for Sass compilation to improve performance. It shares the resolution and package root caches across compile requests in sass-language.ts and moves the directory cache in SassCompiler to a class-level property. The review feedback identifies a critical correctness issue where relative imports not starting with . are incorrectly cached globally, which can be resolved by qualifying all non-pkg: imports with the containing URL. Additionally, it is recommended to expose a public clearCache() method on SassCompiler to allow clearing the directory cache during rebuilds.

Comment thread packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts Outdated
Comment thread packages/angular/build/src/tools/sass/sass-service.ts
@alan-agius4 alan-agius4 added the target: minor This PR is targeted for the next minor release label Sep 8, 2026
@alan-agius4
alan-agius4 requested a review from clydin September 8, 2026 14:56
@alan-agius4 alan-agius4 added the action: review The PR is still awaiting reviews from at least one requested reviewer label Sep 8, 2026
…ss stylesheets

Previously, Sass resolution caches (resolutionCache and packageRootCache) in sass-language.ts and the filesystem directory entry cache (directoryCache) in sass-service.ts were created anew for every individual stylesheet compilation request.

When compiling applications that use component styles importing shared design tokens or library stylesheets (such as @angular/material or deep-imported @material/* packages), rebasing importers repeatedly invoked synchronous fs.readdirSync across the same node module package directories, and re-executed esbuild resolution calls.

To eliminate redundant disk I/O and resolution overhead:
- Hoist directoryCache to an instance property of SassCompiler, persisting directory listings across compile calls and clearing them upon compiler shutdown in close().
- Hoist resolutionCache and packageRootCache to module-scoped caches in sass-language.ts, clearing them during shutdownSassWorkerPool().
- Contextualize relative import resolution cache keys using the containing URL to preserve correctness while allowing package specifiers to resolve once across all stylesheets.

In benchmarks on an application with 50 component SCSS stylesheets importing @angular/material, synchronous fs.readdirSync calls dropped from 2,900 to 205 (-92.9%), build.resolve calls dropped from 100 to 2 (-98.0%), and compilation time improved by up to 26.4%.
Comment thread packages/angular/build/src/tools/esbuild/stylesheets/sass-language.ts Outdated
@alan-agius4 alan-agius4 added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Sep 9, 2026
@alan-agius4
alan-agius4 merged commit 0a137f9 into angular:main Sep 9, 2026
40 checks passed
@alan-agius4

Copy link
Copy Markdown
Collaborator Author

This PR was merged into the repository. The changes were merged into the following branches:

@alan-agius4
alan-agius4 deleted the perf/sass-caching branch September 9, 2026 16:34
alan-agius4 added a commit to alan-agius4/ng-packagr that referenced this pull request Sep 9, 2026
…tylesheets

Port angular/angular-cli#34041 to ng-packagr.

Previously, Sass resolution caches (resolutionCache and packageRootCache) in sass-language.ts and the filesystem directory entry cache (directoryCache) in sass-service.ts were created anew for every individual stylesheet compilation request.

To eliminate redundant disk I/O and resolution overhead:
- Hoist directoryCache to an instance property of SassCompiler, persisting directory listings across compile calls and clearing them upon compiler shutdown in close() or clearCache().
- Hoist resolutionCache and packageRootCache to module-scoped caches in sass-language.ts, clearing them via resetSassWorkerPoolCaches() during shutdownSassWorkerPool() or when invalidating component stylesheets.
- Contextualize relative import resolution cache keys and package root cache keys using the containing URL to preserve correctness while allowing package specifiers to resolve once across all stylesheets.
alan-agius4 added a commit to ng-packagr/ng-packagr that referenced this pull request Sep 9, 2026
…tylesheets

Port angular/angular-cli#34041 to ng-packagr.

Previously, Sass resolution caches (resolutionCache and packageRootCache) in sass-language.ts and the filesystem directory entry cache (directoryCache) in sass-service.ts were created anew for every individual stylesheet compilation request.

To eliminate redundant disk I/O and resolution overhead:
- Hoist directoryCache to an instance property of SassCompiler, persisting directory listings across compile calls and clearing them upon compiler shutdown in close() or clearCache().
- Hoist resolutionCache and packageRootCache to module-scoped caches in sass-language.ts, clearing them via resetSassWorkerPoolCaches() during shutdownSassWorkerPool() or when invalidating component stylesheets.
- Contextualize relative import resolution cache keys and package root cache keys using the containing URL to preserve correctness while allowing package specifiers to resolve once across all stylesheets.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

action: merge The PR is ready for merge by the caretaker area: @angular/build area: performance Issues related to performance target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants