@@ -143,13 +143,15 @@ export class AngularServerApp {
143
143
private readonly textDecoder = new TextEncoder ( ) ;
144
144
145
145
/**
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 .
148
148
*
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.
151
150
*/
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 ) ;
153
155
154
156
/**
155
157
* Handles an incoming HTTP request by serving prerendered content, performing server-side rendering,
@@ -198,7 +200,6 @@ export class AngularServerApp {
198
200
*
199
201
* @param request - The incoming HTTP request for serving a static page.
200
202
* @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.
202
203
* @returns A promise that resolves to a `Response` object if the prerendered page is found, or `null`.
203
204
*/
204
205
private async handleServe (
@@ -247,7 +248,6 @@ export class AngularServerApp {
247
248
*
248
249
* @param request - The incoming HTTP request to be processed.
249
250
* @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.
251
251
* @param requestContext - Optional additional context for rendering, such as request metadata.
252
252
*
253
253
* @returns A promise that resolves to the rendered response, or null if no matching route is found.
@@ -343,8 +343,8 @@ export class AngularServerApp {
343
343
const stream = new ReadableStream ( {
344
344
start : async ( controller ) => {
345
345
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 ) ;
348
348
controller . close ( ) ;
349
349
} ,
350
350
} ) ;
@@ -355,33 +355,19 @@ export class AngularServerApp {
355
355
/**
356
356
* Inlines critical CSS into the given HTML content.
357
357
*
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.
361
360
* @returns A promise that resolves to the HTML with inlined critical CSS.
362
361
*/
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 ;
365
364
366
365
if ( ! inlineCriticalCssProcessor ) {
367
366
return html ;
368
367
}
369
368
370
369
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 ) ;
385
371
} catch ( error ) {
386
372
// eslint-disable-next-line no-console
387
373
console . error ( `An error occurred while inlining critical CSS for: ${ url } .` , error ) ;
@@ -390,6 +376,41 @@ export class AngularServerApp {
390
376
}
391
377
}
392
378
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
+
393
414
/**
394
415
* Constructs the asset path on the server based on the provided HTTP request.
395
416
*
0 commit comments