diff --git a/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html b/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html index 2664fac1b4..663af7b9e0 100644 --- a/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/nested-figure-embed/expected.html @@ -37,6 +37,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html b/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html index 4e5bf50487..d3cb20399f 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-spotify-embed-outside-viewport-with-subsequent-script/expected.html @@ -20,6 +20,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html index 8d6f333719..c781f868e2 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-inside-viewport/expected.html @@ -24,6 +24,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html index ffea99e318..e7e3dd4e2d 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport-on-mobile/expected.html @@ -24,6 +24,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html index d058bd23a0..d823c0d737 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-wordpress-tv-embed-outside-viewport/expected.html @@ -21,6 +21,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html index 82f201d47f..88b87ac769 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-inside-viewport-with-only-mobile-url-metrics/expected.html @@ -18,6 +18,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html index 5d0daf79f9..722dba432d 100644 --- a/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/single-youtube-embed-outside-viewport-with-only-mobile-url-metrics/expected.html @@ -16,6 +16,6 @@ - + diff --git a/plugins/embed-optimizer/tests/test-cases/too-many-bookmarks/expected.html b/plugins/embed-optimizer/tests/test-cases/too-many-bookmarks/expected.html index 53c99c388b..32596d6632 100644 --- a/plugins/embed-optimizer/tests/test-cases/too-many-bookmarks/expected.html +++ b/plugins/embed-optimizer/tests/test-cases/too-many-bookmarks/expected.html @@ -14,6 +14,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/background-image-outside-viewport-with-desktop-metrics-missing/expected.html b/plugins/image-prioritizer/tests/test-cases/background-image-outside-viewport-with-desktop-metrics-missing/expected.html index 87d29f21d8..f04714e9e8 100644 --- a/plugins/image-prioritizer/tests/test-cases/background-image-outside-viewport-with-desktop-metrics-missing/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/background-image-outside-viewport-with-desktop-metrics-missing/expected.html @@ -10,6 +10,6 @@

Pretend this is a super long paragraph that pushes the next div out of the initial viewport.

This is so background!
- + diff --git a/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-fully-incomplete-sample-data/expected.html b/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-fully-incomplete-sample-data/expected.html index a5ebd3f556..51e5f8d0b9 100644 --- a/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-fully-incomplete-sample-data/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-fully-incomplete-sample-data/expected.html @@ -11,6 +11,6 @@ Foo Bar - + diff --git a/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-old-xpath-format/expected.html b/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-old-xpath-format/expected.html index 760ef228b0..59e930027f 100644 --- a/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-old-xpath-format/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/common-lcp-image-with-old-xpath-format/expected.html @@ -9,6 +9,6 @@
Foo
- + diff --git a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-all-breakpoints/expected.html b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-all-breakpoints/expected.html index f20729ad2c..17dc0cd6d6 100644 --- a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-all-breakpoints/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-all-breakpoints/expected.html @@ -18,6 +18,6 @@ Desktop Logo Desktop Logo - + diff --git a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-non-consecutive-viewport-groups-with-missing-data-for-middle-group/expected.html b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-non-consecutive-viewport-groups-with-missing-data-for-middle-group/expected.html index aa4c663120..3c4939eb5e 100644 --- a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-non-consecutive-viewport-groups-with-missing-data-for-middle-group/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-non-consecutive-viewport-groups-with-missing-data-for-middle-group/expected.html @@ -11,6 +11,6 @@ Mobile Logo Desktop Logo - + diff --git a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints-and-one-is-stale/expected.html b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints-and-one-is-stale/expected.html index e0f89f5215..7dbf52e158 100644 --- a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints-and-one-is-stale/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints-and-one-is-stale/expected.html @@ -12,6 +12,6 @@

New paragraph since URL Metrics were captured!

Desktop Logo - + diff --git a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints/expected.html b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints/expected.html index de5ee6cb87..27e3f84b13 100644 --- a/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/different-lcp-elements-for-two-non-consecutive-breakpoints/expected.html @@ -12,6 +12,6 @@ Mobile Logo Desktop Logo - + diff --git a/plugins/image-prioritizer/tests/test-cases/fetch-priority-high-on-lcp-image-common-on-mobile-and-desktop-with-url-metrics-missing-in-other-groups/expected.html b/plugins/image-prioritizer/tests/test-cases/fetch-priority-high-on-lcp-image-common-on-mobile-and-desktop-with-url-metrics-missing-in-other-groups/expected.html index edfa5b1440..ac01326acc 100644 --- a/plugins/image-prioritizer/tests/test-cases/fetch-priority-high-on-lcp-image-common-on-mobile-and-desktop-with-url-metrics-missing-in-other-groups/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/fetch-priority-high-on-lcp-image-common-on-mobile-and-desktop-with-url-metrics-missing-in-other-groups/expected.html @@ -11,6 +11,6 @@
Foo
- + diff --git a/plugins/image-prioritizer/tests/test-cases/img-non-native-lazy-loading/expected.html b/plugins/image-prioritizer/tests/test-cases/img-non-native-lazy-loading/expected.html index b3c0ac6105..058c95b80c 100644 --- a/plugins/image-prioritizer/tests/test-cases/img-non-native-lazy-loading/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/img-non-native-lazy-loading/expected.html @@ -12,6 +12,6 @@ Bar - + diff --git a/plugins/image-prioritizer/tests/test-cases/lcp-element-external-background-image-present-in-document-and-partially-populated-samples/expected.html b/plugins/image-prioritizer/tests/test-cases/lcp-element-external-background-image-present-in-document-and-partially-populated-samples/expected.html index 1cb1bc454b..59a04ce5d5 100644 --- a/plugins/image-prioritizer/tests/test-cases/lcp-element-external-background-image-present-in-document-and-partially-populated-samples/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/lcp-element-external-background-image-present-in-document-and-partially-populated-samples/expected.html @@ -11,6 +11,6 @@

Example

- + diff --git a/plugins/image-prioritizer/tests/test-cases/multiple-videos-on-all-breakpoints/expected.html b/plugins/image-prioritizer/tests/test-cases/multiple-videos-on-all-breakpoints/expected.html index 0506d55df8..1e04882043 100644 --- a/plugins/image-prioritizer/tests/test-cases/multiple-videos-on-all-breakpoints/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/multiple-videos-on-all-breakpoints/expected.html @@ -15,6 +15,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/multiple-videos-with-desktop-metrics-missing/expected.html b/plugins/image-prioritizer/tests/test-cases/multiple-videos-with-desktop-metrics-missing/expected.html index 647f07c5fd..739fb2cc27 100644 --- a/plugins/image-prioritizer/tests/test-cases/multiple-videos-with-desktop-metrics-missing/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/multiple-videos-with-desktop-metrics-missing/expected.html @@ -14,6 +14,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-but-server-side-heuristics-added-fetchpriority-high/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-but-server-side-heuristics-added-fetchpriority-high/expected.html index 0a1eb948eb..45e8ff0bfc 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-but-server-side-heuristics-added-fetchpriority-high/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-but-server-side-heuristics-added-fetchpriority-high/expected.html @@ -12,6 +12,6 @@ Baz Qux - + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-for-image-without-src/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-for-image-without-src/expected.html index 25699435ff..04ad38a08f 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-for-image-without-src/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-for-image-without-src/expected.html @@ -10,6 +10,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-background-image/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-background-image/expected.html index 04689c91a2..88c44d6de1 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-background-image/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-background-image/expected.html @@ -9,6 +9,6 @@
This is so background!
- + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-image/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-image/expected.html index e3a29b57b2..e89080aaf9 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-image/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-data-url-image/expected.html @@ -9,6 +9,6 @@
- + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-non-background-image-style/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-non-background-image-style/expected.html index a18b0263ef..b859e92914 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-non-background-image-style/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics-with-non-background-image-style/expected.html @@ -9,6 +9,6 @@
This is so background!
- + diff --git a/plugins/image-prioritizer/tests/test-cases/no-url-metrics/expected.html b/plugins/image-prioritizer/tests/test-cases/no-url-metrics/expected.html index 66b3be8211..ce5aa92785 100644 --- a/plugins/image-prioritizer/tests/test-cases/no-url-metrics/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/no-url-metrics/expected.html @@ -11,6 +11,6 @@

Pretend this is a super long paragraph that pushes the next div out of the initial viewport.

This is so background!
- + diff --git a/plugins/image-prioritizer/tests/test-cases/only-mobile-and-desktop-groups-are-populated/expected.html b/plugins/image-prioritizer/tests/test-cases/only-mobile-and-desktop-groups-are-populated/expected.html index 728a0498e4..4c30816051 100644 --- a/plugins/image-prioritizer/tests/test-cases/only-mobile-and-desktop-groups-are-populated/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/only-mobile-and-desktop-groups-are-populated/expected.html @@ -36,6 +36,6 @@

First Post

- + diff --git a/plugins/image-prioritizer/tests/test-cases/picture-element-as-lcp-tablet-and-desktop-metrics-missing/expected.html b/plugins/image-prioritizer/tests/test-cases/picture-element-as-lcp-tablet-and-desktop-metrics-missing/expected.html index 606e488de5..d5fd5c6d8e 100644 --- a/plugins/image-prioritizer/tests/test-cases/picture-element-as-lcp-tablet-and-desktop-metrics-missing/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/picture-element-as-lcp-tablet-and-desktop-metrics-missing/expected.html @@ -14,6 +14,6 @@ Foo - + diff --git a/plugins/image-prioritizer/tests/test-cases/preload-links-with-one-half-stale-group/expected.html b/plugins/image-prioritizer/tests/test-cases/preload-links-with-one-half-stale-group/expected.html index a1e30f3012..8c559ddcf7 100644 --- a/plugins/image-prioritizer/tests/test-cases/preload-links-with-one-half-stale-group/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/preload-links-with-one-half-stale-group/expected.html @@ -35,6 +35,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/url-metric-only-captured-for-one-breakpoint/expected.html b/plugins/image-prioritizer/tests/test-cases/url-metric-only-captured-for-one-breakpoint/expected.html index a98ce9eced..e153caccc4 100644 --- a/plugins/image-prioritizer/tests/test-cases/url-metric-only-captured-for-one-breakpoint/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/url-metric-only-captured-for-one-breakpoint/expected.html @@ -11,7 +11,7 @@ Foo - + diff --git a/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-collected/expected.html b/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-collected/expected.html index 954f888e6d..fb18fa6897 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-collected/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-collected/expected.html @@ -12,6 +12,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-missing/expected.html b/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-missing/expected.html index be68091961..81196ab629 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-missing/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-with-large-poster-and-desktop-url-metrics-missing/expected.html @@ -12,6 +12,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-all-breakpoints/expected.html b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-all-breakpoints/expected.html index 27ca94a1a2..afcb6c5385 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-all-breakpoints/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-all-breakpoints/expected.html @@ -10,6 +10,6 @@
- + diff --git a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-desktop-only/expected.html b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-desktop-only/expected.html index 870412d433..4f8a80ae9a 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-desktop-only/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-desktop-only/expected.html @@ -15,6 +15,6 @@ - + diff --git a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-mobile-and-desktop-but-not-tablet/expected.html b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-mobile-and-desktop-but-not-tablet/expected.html index 3e49ed983f..d6f906ceea 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-mobile-and-desktop-but-not-tablet/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-with-poster-lcp-element-on-mobile-and-desktop-but-not-tablet/expected.html @@ -13,6 +13,6 @@ Tablet header - + diff --git a/plugins/image-prioritizer/tests/test-cases/video-without-poster-lcp-element-on-desktop-only/expected.html b/plugins/image-prioritizer/tests/test-cases/video-without-poster-lcp-element-on-desktop-only/expected.html index 4612655ee4..cae6648bb7 100644 --- a/plugins/image-prioritizer/tests/test-cases/video-without-poster-lcp-element-on-desktop-only/expected.html +++ b/plugins/image-prioritizer/tests/test-cases/video-without-poster-lcp-element-on-desktop-only/expected.html @@ -14,6 +14,6 @@ - + diff --git a/plugins/optimization-detective/detect-loader.js b/plugins/optimization-detective/detect-loader.js new file mode 100644 index 0000000000..a748f6630f --- /dev/null +++ b/plugins/optimization-detective/detect-loader.js @@ -0,0 +1,35 @@ +/** + * Loads the detect module after the page has loaded. + * + * This prevents a high-priority script module network request from competing with other critical resources. This + * JavaScript file must contain a single top-level function which is not exported. The file is inlined as part of + * another module which wraps the function in an IIFE. + * + * @since 1.0.0 + * + * @param {string} detectSrc - The URL to detect.js. + * @param {import("./detect.js").DetectFunctionArgs} detectArgs - The arguments exported from PHP. + */ +// eslint-disable-next-line no-unused-vars +async function load( detectSrc, detectArgs ) { + // Wait until the resources on the page have fully loaded. + await new Promise( ( resolve ) => { + if ( document.readyState === 'complete' ) { + resolve(); + } else { + window.addEventListener( 'load', resolve, { once: true } ); + } + } ); + + // Wait yet further until idle. + if ( typeof requestIdleCallback === 'function' ) { + await new Promise( ( resolve ) => { + requestIdleCallback( resolve ); + } ); + } + + const detect = /** @type {import("./detect.js").DetectFunction} */ ( + ( await import( detectSrc ) ).default + ); + await detect( detectArgs ); +} diff --git a/plugins/optimization-detective/detect.js b/plugins/optimization-detective/detect.js index ad72c15b2c..a599098ebc 100644 --- a/plugins/optimization-detective/detect.js +++ b/plugins/optimization-detective/detect.js @@ -508,28 +508,46 @@ function debounceCompressUrlMetric() { * @typedef {{groups: Array<{url_metrics: Array}>}} CollectionDebugData */ +/** + * Args for the detect function. + * + * @since 1.0.0 + * + * @typedef {Object} DetectFunctionArgs + * @property {string[]} extensionModuleUrls - URLs for extension script modules to import. + * @property {number} minViewportAspectRatio - Minimum aspect ratio allowed for the viewport. + * @property {number} maxViewportAspectRatio - Maximum aspect ratio allowed for the viewport. + * @property {boolean} isDebug - Whether to show debug messages. + * @property {string} restApiEndpoint - URL for where to send the detection data. + * @property {string} [restApiNonce] - Nonce for the REST API when the user is logged-in. + * @property {boolean} gzdecodeAvailable - Whether application/gzip can be sent to the REST API. + * @property {number} maxUrlMetricSize - Maximum size of the URL Metric to send. + * @property {string} currentETag - Current ETag. + * @property {string} currentUrl - Current URL. + * @property {string} urlMetricSlug - Slug for URL Metric. + * @property {number|null} cachePurgePostId - Cache purge post ID. + * @property {string} urlMetricHMAC - HMAC for URL Metric storage. + * @property {URLMetricGroupStatus[]} urlMetricGroupStatuses - URL Metric group statuses. + * @property {number} storageLockTTL - The TTL (in seconds) for the URL Metric storage lock. + * @property {number} freshnessTTL - The freshness age (TTL) for a given URL Metric. + * @property {string} webVitalsLibrarySrc - The URL for the web-vitals library. + * @property {CollectionDebugData} [urlMetricGroupCollection] - URL Metric group collection, when in debug mode. + */ + +/** + * The detect function. + * + * @since 1.0.0 + * @callback DetectFunction + * @param {DetectFunctionArgs} args - The arguments for the function. + * @return {Promise} + */ + /** * Detects the LCP element, loaded images, client viewport, and store for future optimizations. * - * @param {Object} args - Args. - * @param {string[]} args.extensionModuleUrls - URLs for extension script modules to import. - * @param {number} args.minViewportAspectRatio - Minimum aspect ratio allowed for the viewport. - * @param {number} args.maxViewportAspectRatio - Maximum aspect ratio allowed for the viewport. - * @param {boolean} args.isDebug - Whether to show debug messages. - * @param {string} args.restApiEndpoint - URL for where to send the detection data. - * @param {string} [args.restApiNonce] - Nonce for the REST API when the user is logged-in. - * @param {boolean} args.gzdecodeAvailable - Whether application/gzip can be sent to the REST API. - * @param {number} args.maxUrlMetricSize - Maximum size of the URL Metric to send. - * @param {string} args.currentETag - Current ETag. - * @param {string} args.currentUrl - Current URL. - * @param {string} args.urlMetricSlug - Slug for URL Metric. - * @param {number|null} args.cachePurgePostId - Cache purge post ID. - * @param {string} args.urlMetricHMAC - HMAC for URL Metric storage. - * @param {URLMetricGroupStatus[]} args.urlMetricGroupStatuses - URL Metric group statuses. - * @param {number} args.storageLockTTL - The TTL (in seconds) for the URL Metric storage lock. - * @param {number} args.freshnessTTL - The freshness age (TTL) for a given URL Metric. - * @param {string} args.webVitalsLibrarySrc - The URL for the web-vitals library. - * @param {CollectionDebugData} [args.urlMetricGroupCollection] - URL Metric group collection, when in debug mode. + * @type {DetectFunction} + * @param {DetectFunctionArgs} args - Args. */ export default async function detect( { minViewportAspectRatio, @@ -635,31 +653,6 @@ export default async function detect( { return; } - // 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 ); - } ); - } - // TODO: Does this make sense here? Should it be moved up above the isViewportNeeded condition? // As an alternative to this, the od_print_detection_script() function can short-circuit if the // od_is_url_metric_storage_locked() function returns true. However, the downside with that is page caching could @@ -842,12 +835,19 @@ export default async function detect( { /** @type {string[]} */ const initializingExtensionModuleUrls = []; - for ( const extensionModuleUrl of extensionModuleUrls ) { - try { - /** @type {Extension} */ - const extension = await import( extensionModuleUrl ); + // Load all extensions in parallel. + await Promise.all( + extensionModuleUrls.map( async ( extensionModuleUrl ) => { + const extension = /** @type {Extension} */ await import( + extensionModuleUrl + ); extensions.set( extensionModuleUrl, extension ); + } ) + ); + // Initialize extensions. + for ( const [ extensionModuleUrl, extension ] of extensions.entries() ) { + try { const extensionLogger = createLogger( isDebug, `[Optimization Detective: ${ diff --git a/plugins/optimization-detective/detection.php b/plugins/optimization-detective/detection.php index efad149448..8fb4e7d48f 100644 --- a/plugins/optimization-detective/detection.php +++ b/plugins/optimization-detective/detection.php @@ -151,7 +151,8 @@ static function ( OD_URL_Metric_Group $group ): array { return wp_get_inline_script_tag( sprintf( - 'import detect from %s; detect( %s );', + '( %s )( %s, %s );', + file_get_contents( __DIR__ . '/' . od_get_asset_path( 'detect-loader.js' ) ), // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- It's a local filesystem path not a remote request. wp_json_encode( plugins_url( add_query_arg( 'ver', OPTIMIZATION_DETECTIVE_VERSION, od_get_asset_path( 'detect.js' ) ), __FILE__ ) ), wp_json_encode( $detect_args ) ), diff --git a/plugins/optimization-detective/tests/class-optimization-detective-test-helpers.php b/plugins/optimization-detective/tests/class-optimization-detective-test-helpers.php index 66c813070a..90dc734333 100644 --- a/plugins/optimization-detective/tests/class-optimization-detective-test-helpers.php +++ b/plugins/optimization-detective/tests/class-optimization-detective-test-helpers.php @@ -290,6 +290,8 @@ static function ( $matches ) { $text = trim( $text ); if ( 1 === preg_match( '/^(import|const) \w+/', $text, $matches ) ) { $text = '/* ' . $matches[0] . ' ... */'; + } elseif ( 1 === preg_match( '/^\( async function load.+\);$/s', $text ) ) { + $text = '/* detect loader */'; } return $start_tag . $text . $end_tag; }, diff --git a/plugins/optimization-detective/tests/test-cases/admin-bar/expected.html b/plugins/optimization-detective/tests/test-cases/admin-bar/expected.html index 9015b039bd..d84db44738 100644 --- a/plugins/optimization-detective/tests/test-cases/admin-bar/expected.html +++ b/plugins/optimization-detective/tests/test-cases/admin-bar/expected.html @@ -16,6 +16,6 @@

- + diff --git a/plugins/optimization-detective/tests/test-cases/many-images/expected.html b/plugins/optimization-detective/tests/test-cases/many-images/expected.html index 0f5367a1e7..6336800ddd 100644 --- a/plugins/optimization-detective/tests/test-cases/many-images/expected.html +++ b/plugins/optimization-detective/tests/test-cases/many-images/expected.html @@ -1008,6 +1008,6 @@ Foo Foo - + diff --git a/plugins/optimization-detective/tests/test-cases/no-url-metrics/expected.html b/plugins/optimization-detective/tests/test-cases/no-url-metrics/expected.html index fcab8d87aa..fd352f52b6 100644 --- a/plugins/optimization-detective/tests/test-cases/no-url-metrics/expected.html +++ b/plugins/optimization-detective/tests/test-cases/no-url-metrics/expected.html @@ -9,6 +9,6 @@
Foo
- + diff --git a/plugins/optimization-detective/tests/test-cases/noscript/expected.html b/plugins/optimization-detective/tests/test-cases/noscript/expected.html index 83a9f62289..7d65ce4d7a 100644 --- a/plugins/optimization-detective/tests/test-cases/noscript/expected.html +++ b/plugins/optimization-detective/tests/test-cases/noscript/expected.html @@ -11,6 +11,6 @@ - + diff --git a/plugins/optimization-detective/tests/test-cases/preload-link/expected.html b/plugins/optimization-detective/tests/test-cases/preload-link/expected.html index 1ff3771d1a..8208541495 100644 --- a/plugins/optimization-detective/tests/test-cases/preload-link/expected.html +++ b/plugins/optimization-detective/tests/test-cases/preload-link/expected.html @@ -10,6 +10,6 @@
- + diff --git a/plugins/optimization-detective/tests/test-cases/tag-track-opt-in/expected.html b/plugins/optimization-detective/tests/test-cases/tag-track-opt-in/expected.html index 3cd244275c..b3d821466f 100644 --- a/plugins/optimization-detective/tests/test-cases/tag-track-opt-in/expected.html +++ b/plugins/optimization-detective/tests/test-cases/tag-track-opt-in/expected.html @@ -12,6 +12,6 @@
- + diff --git a/plugins/optimization-detective/tests/test-cases/video/expected.html b/plugins/optimization-detective/tests/test-cases/video/expected.html index f1a4fc31c1..8204aa2439 100644 --- a/plugins/optimization-detective/tests/test-cases/video/expected.html +++ b/plugins/optimization-detective/tests/test-cases/video/expected.html @@ -12,6 +12,6 @@ - + diff --git a/plugins/optimization-detective/tests/test-cases/xhtml-response/expected.html b/plugins/optimization-detective/tests/test-cases/xhtml-response/expected.html index 7a2c34693e..6bf4e96222 100644 --- a/plugins/optimization-detective/tests/test-cases/xhtml-response/expected.html +++ b/plugins/optimization-detective/tests/test-cases/xhtml-response/expected.html @@ -11,6 +11,6 @@

Foo

- + diff --git a/plugins/optimization-detective/tests/test-detection.php b/plugins/optimization-detective/tests/test-detection.php index 09b6cfbdec..71b5734e95 100644 --- a/plugins/optimization-detective/tests/test-detection.php +++ b/plugins/optimization-detective/tests/test-detection.php @@ -222,7 +222,7 @@ public function test_od_get_detection_script_returns_script( Closure $set_up, ar $script = od_get_detection_script( $slug, $group_collection ); $this->assertStringContainsString( '