@@ -143,13 +143,15 @@ export class AngularServerApp {
143143 private readonly textDecoder = new TextEncoder ( ) ;
144144
145145 /**
146- * Cache for storing critical CSS for pages .
147- * Stores a maximum of MAX_INLINE_CSS_CACHE_ENTRIES entries .
146+ * A cache that stores critical CSS to avoid re-processing for every request, improving performance .
147+ * This cache uses a Least Recently Used (LRU) eviction policy .
148148 *
149- * Uses an LRU (Least Recently Used) eviction policy, meaning that when the cache is full,
150- * the least recently accessed page's critical CSS will be removed to make space for new entries.
149+ * @see {@link MAX_INLINE_CSS_CACHE_ENTRIES } for the maximum number of entries this cache can hold.
151150 */
152- private readonly criticalCssLRUCache = new LRUCache < string , string > ( MAX_INLINE_CSS_CACHE_ENTRIES ) ;
151+ private readonly criticalCssLRUCache = new LRUCache <
152+ string ,
153+ { shaOfContentPreInlinedCss : string ; contentWithCriticialCSS : Uint8Array < ArrayBufferLike > }
154+ > ( MAX_INLINE_CSS_CACHE_ENTRIES ) ;
153155
154156 /**
155157 * Handles an incoming HTTP request by serving prerendered content, performing server-side rendering,
@@ -198,7 +200,6 @@ export class AngularServerApp {
198200 *
199201 * @param request - The incoming HTTP request for serving a static page.
200202 * @param matchedRoute - The metadata of the matched route for rendering.
201- * If not provided, the method attempts to find a matching route based on the request URL.
202203 * @returns A promise that resolves to a `Response` object if the prerendered page is found, or `null`.
203204 */
204205 private async handleServe (
@@ -247,7 +248,6 @@ export class AngularServerApp {
247248 *
248249 * @param request - The incoming HTTP request to be processed.
249250 * @param matchedRoute - The metadata of the matched route for rendering.
250- * If not provided, the method attempts to find a matching route based on the request URL.
251251 * @param requestContext - Optional additional context for rendering, such as request metadata.
252252 *
253253 * @returns A promise that resolves to the rendered response, or null if no matching route is found.
@@ -343,8 +343,8 @@ export class AngularServerApp {
343343 const stream = new ReadableStream ( {
344344 start : async ( controller ) => {
345345 const renderedHtml = await result . content ( ) ;
346- const finalHtml = await this . inlineCriticalCss ( renderedHtml , url , true ) ;
347- controller . enqueue ( this . textDecoder . encode ( finalHtml ) ) ;
346+ const finalHtml = await this . inlineCriticalCssWithCache ( renderedHtml , url ) ;
347+ controller . enqueue ( finalHtml ) ;
348348 controller . close ( ) ;
349349 } ,
350350 } ) ;
@@ -355,33 +355,19 @@ export class AngularServerApp {
355355 /**
356356 * Inlines critical CSS into the given HTML content.
357357 *
358- * @param html - The HTML content to process.
359- * @param url - The URL associated with the request, for logging purposes.
360- * @param cache - A flag to indicate if the result should be cached.
358+ * @param html The HTML content to process.
359+ * @param url The URL associated with the request, for logging purposes.
361360 * @returns A promise that resolves to the HTML with inlined critical CSS.
362361 */
363- private async inlineCriticalCss ( html : string , url : URL , cache = false ) : Promise < string > {
364- const { inlineCriticalCssProcessor, criticalCssLRUCache } = this ;
362+ private async inlineCriticalCss ( html : string , url : URL ) : Promise < string > {
363+ const { inlineCriticalCssProcessor } = this ;
365364
366365 if ( ! inlineCriticalCssProcessor ) {
367366 return html ;
368367 }
369368
370369 try {
371- if ( ! cache ) {
372- return await inlineCriticalCssProcessor . process ( html ) ;
373- }
374-
375- const cacheKey = await sha256 ( html ) ;
376- const cachedHtml = criticalCssLRUCache . get ( cacheKey ) ;
377- if ( cachedHtml ) {
378- return cachedHtml ;
379- }
380-
381- const processedHtml = await inlineCriticalCssProcessor . process ( html ) ;
382- criticalCssLRUCache . put ( cacheKey , processedHtml ) ;
383-
384- return processedHtml ;
370+ return await inlineCriticalCssProcessor . process ( html ) ;
385371 } catch ( error ) {
386372 // eslint-disable-next-line no-console
387373 console . error ( `An error occurred while inlining critical CSS for: ${ url } .` , error ) ;
@@ -390,6 +376,41 @@ export class AngularServerApp {
390376 }
391377 }
392378
379+ /**
380+ * Inlines critical CSS into the given HTML content.
381+ * This method uses a cache to avoid reprocessing the same HTML content multiple times.
382+ *
383+ * @param html The HTML content to process.
384+ * @param url The URL associated with the request, for logging purposes.
385+ * @returns A promise that resolves to the HTML with inlined critical CSS.
386+ */
387+ private async inlineCriticalCssWithCache (
388+ html : string ,
389+ url : URL ,
390+ ) : Promise < Uint8Array < ArrayBufferLike > > {
391+ const { inlineCriticalCssProcessor, criticalCssLRUCache, textDecoder } = this ;
392+
393+ if ( ! inlineCriticalCssProcessor ) {
394+ return textDecoder . encode ( html ) ;
395+ }
396+
397+ const cacheKey = url . toString ( ) ;
398+ const cached = criticalCssLRUCache . get ( cacheKey ) ;
399+ const shaOfContentPreInlinedCss = await sha256 ( html ) ;
400+ if ( cached ?. shaOfContentPreInlinedCss === shaOfContentPreInlinedCss ) {
401+ return cached . contentWithCriticialCSS ;
402+ }
403+
404+ const processedHtml = await this . inlineCriticalCss ( html , url ) ;
405+ const finalHtml = textDecoder . encode ( processedHtml ) ;
406+ criticalCssLRUCache . put ( cacheKey , {
407+ shaOfContentPreInlinedCss,
408+ contentWithCriticialCSS : finalHtml ,
409+ } ) ;
410+
411+ return finalHtml ;
412+ }
413+
393414 /**
394415 * Constructs the asset path on the server based on the provided HTTP request.
395416 *
0 commit comments