From 7affa5775427e92ef6e949c879765b7c8aa172da Mon Sep 17 00:00:00 2001 From: arturovt Date: Fri, 17 Nov 2023 12:23:12 +0200 Subject: [PATCH] fix(common): scan images once page is loaded (#52991) This commit updates the implementation of the `ImagePerformanceWarning` and runs the image scan even if the page has already been loaded. The `window.load` event would never fire if the page has already been loaded; that's why we're checking for the document's ready state. PR Close #52991 --- packages/core/src/image_performance_warning.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/core/src/image_performance_warning.ts b/packages/core/src/image_performance_warning.ts index 7bc0c2194d9..1a467b76619 100644 --- a/packages/core/src/image_performance_warning.ts +++ b/packages/core/src/image_performance_warning.ts @@ -22,7 +22,6 @@ const SCAN_DELAY = 200; const OVERSIZED_IMAGE_TOLERANCE = 1200; - @Injectable({providedIn: 'root'}) export class ImagePerformanceWarning implements OnDestroy { // Map of full image URLs -> original `ngSrc` values. @@ -38,7 +37,8 @@ export class ImagePerformanceWarning implements OnDestroy { return; } this.observer = this.initPerformanceObserver(); - const win = getDocument().defaultView; + const doc = getDocument(); + const win = doc.defaultView; if (typeof win !== 'undefined') { this.window = win; // Wait to avoid race conditions where LCP image triggers @@ -49,7 +49,16 @@ export class ImagePerformanceWarning implements OnDestroy { // Angular doesn't have to run change detection whenever any asynchronous tasks are invoked in // the scope of this functionality. this.ngZone.runOutsideAngular(() => { - this.window?.addEventListener('load', waitToScan, {once: true}); + // Consider the case when the application is created and destroyed multiple times. + // Typically, applications are created instantly once the page is loaded, and the + // `window.load` listener is always triggered. However, the `window.load` event will never + // be fired if the page is loaded, and the application is created later. Checking for + // `readyState` is the easiest way to determine whether the page has been loaded or not. + if (doc.readyState === 'complete') { + waitToScan(); + } else { + this.window?.addEventListener('load', waitToScan, {once: true}); + } }); } }