Skip to content

Commit

Permalink
Merge pull request #978 from WordPress/add/ilo-wait-until-idle
Browse files Browse the repository at this point in the history
Wait until idle before starting detection
  • Loading branch information
westonruter authored Feb 9, 2024
2 parents 77dfbaf + dcdce43 commit 7761a9b
Showing 1 changed file with 48 additions and 38 deletions.
86 changes: 48 additions & 38 deletions modules/images/image-loading-optimization/detection/detect.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,6 @@ export default async function detect( {
} ) {
const currentTime = getCurrentTime();

// As an alternative to this, the ilo_print_detection_script() function can short-circuit if the
// ilo_is_url_metric_storage_locked() function returns true. However, the downside with that is page caching could
// result in metrics being missed being gathered when a user navigates around a site and primes the page cache.
if ( isStorageLocked( currentTime, storageLockTTL ) ) {
if ( isDebug ) {
warn( 'Aborted detection due to storage being locked.' );
}
return;
}

// Abort running detection logic if it was served in a cached page.
if ( currentTime - serveTime > detectionTimeWindow ) {
if ( isDebug ) {
Expand All @@ -175,20 +165,55 @@ export default async function detect( {
return;
}

// Prevent detection when page is not scrolled to the initial viewport.
// TODO: Does this cause layout/reflow? https://gist.github.com/paulirish/5d52fb081b3570c81e3a
if ( doc.documentElement.scrollTop > 0 ) {
// Abort if the current viewport is not among those which need URL metrics.
if ( ! isViewportNeeded( win.innerWidth, neededMinimumViewportWidths ) ) {
if ( isDebug ) {
warn(
'Aborted detection since initial scroll position of page is not at the top.'
);
log( 'No need for URL metrics from the current viewport.' );
}
return;
}

if ( ! isViewportNeeded( win.innerWidth, neededMinimumViewportWidths ) ) {
// Ensure the DOM is loaded (although it surely already is since we're executing in a module).
await new Promise( ( resolve ) => {
if ( doc.readyState !== 'loading' ) {
resolve();
} else {
doc.addEventListener( 'DOMContentLoaded', resolve, { once: true } );
}
} );

// Wait until the resources on the page have fully loaded.
await new Promise( ( resolve ) => {
if ( doc.readyState === 'complete' ) {
resolve();
} else {
win.addEventListener( 'load', resolve, { once: true } );
}
} );

// Wait yet further until idle.
if ( typeof requestIdleCallback === 'function' ) {
await new Promise( ( resolve ) => {
requestIdleCallback( resolve );
} );
}

// As an alternative to this, the ilo_print_detection_script() function can short-circuit if the
// ilo_is_url_metric_storage_locked() function returns true. However, the downside with that is page caching could
// result in metrics missed from being gathered when a user navigates around a site and primes the page cache.
if ( isStorageLocked( currentTime, storageLockTTL ) ) {
if ( isDebug ) {
log( 'No need for URL metrics from the current viewport.' );
warn( 'Aborted detection due to storage being locked.' );
}
return;
}

// Prevent detection when page is not scrolled to the initial viewport.
if ( doc.documentElement.scrollTop > 0 ) {
if ( isDebug ) {
warn(
'Aborted detection since initial scroll position of page is not at the top.'
);
}
return;
}
Expand All @@ -197,7 +222,6 @@ export default async function detect( {
log( 'Proceeding with detection' );
}

// TODO: This query no longer needs to be done as early as possible since the server is adding the breadcrumbs.
const breadcrumbedElements =
doc.body.querySelectorAll( '[data-ilo-xpath]' );

Expand All @@ -212,15 +236,6 @@ export default async function detect( {
)
);

// Ensure the DOM is loaded (although it surely already is since we're executing in a module).
await new Promise( ( resolve ) => {
if ( doc.readyState !== 'loading' ) {
resolve();
} else {
doc.addEventListener( 'DOMContentLoaded', resolve, { once: true } );
}
} );

/** @type {IntersectionObserverEntry[]} */
const elementIntersections = [];

Expand Down Expand Up @@ -286,15 +301,6 @@ export default async function detect( {
);
} );

// Wait until the resources on the page have fully loaded.
await new Promise( ( resolve ) => {
if ( doc.readyState === 'complete' ) {
resolve();
} else {
win.addEventListener( 'load', resolve, { once: true } );
}
} );

// Stop observing.
disconnectIntersectionObserver();
if ( isDebug ) {
Expand Down Expand Up @@ -348,7 +354,11 @@ export default async function detect( {
log( 'URL metrics:', urlMetrics );
}

// TODO: Wait until idle? Yield to main?
// Yield to main before sending data to server to further break up task.
await new Promise( ( resolve ) => {
setTimeout( resolve, 0 );
} );

try {
const response = await fetch( restApiEndpoint, {
method: 'POST',
Expand Down

0 comments on commit 7761a9b

Please sign in to comment.