From 6ad91bd80dae935b67a5c18b8dfbb95f2cfe10ef Mon Sep 17 00:00:00 2001 From: Robin Lindner Date: Tue, 1 Nov 2022 13:42:30 +0100 Subject: [PATCH] Improve prefetch conditions (#5244) * Improve prefetch * Add changeset --- .changeset/lemon-spies-approve.md | 5 +++ packages/integrations/prefetch/src/client.ts | 34 +++++++++++--------- packages/integrations/prefetch/src/index.ts | 2 +- 3 files changed, 24 insertions(+), 17 deletions(-) create mode 100644 .changeset/lemon-spies-approve.md diff --git a/.changeset/lemon-spies-approve.md b/.changeset/lemon-spies-approve.md new file mode 100644 index 000000000..b7da75bb3 --- /dev/null +++ b/.changeset/lemon-spies-approve.md @@ -0,0 +1,5 @@ +--- +'@astrojs/prefetch': patch +--- + +Do not prefetch if browser is offline or uses 3G diff --git a/packages/integrations/prefetch/src/client.ts b/packages/integrations/prefetch/src/client.ts index f79f42f12..2881085b0 100644 --- a/packages/integrations/prefetch/src/client.ts +++ b/packages/integrations/prefetch/src/client.ts @@ -15,7 +15,7 @@ function shouldPreload({ href }: { href: string }) { window.location.pathname !== url.pathname && !preloaded.has(href) ); - } catch {} + } catch { } return false; } @@ -44,12 +44,11 @@ function onLinkEvent({ target }: Event) { async function preloadHref(link: HTMLAnchorElement) { unobserve(link); - const { href } = link; try { const contents = await fetch(href).then((res) => res.text()); - parser = parser || new DOMParser(); + parser ||= new DOMParser(); const html = parser.parseFromString(contents, 'text/html'); const styles = Array.from(html.querySelectorAll('link[rel="stylesheet"]')); @@ -62,7 +61,7 @@ async function preloadHref(link: HTMLAnchorElement) { return fetch(el.href); }) ); - } catch {} + } catch { } } export interface PrefetchOptions { @@ -84,14 +83,21 @@ export default function prefetch({ selector = 'a[href][rel~="prefetch"]', throttle = 1, }: PrefetchOptions) { - const conn = navigator.connection; + // If the navigator is offline, it is very unlikely that a request can be made successfully + if (!navigator.onLine) { + return Promise.reject(new Error('Cannot prefetch, no network connection')); + } - if (typeof conn !== 'undefined') { - // Don't prefetch if using 2G or if Save-Data is enabled. - if (conn.saveData) { + // `Navigator.connection` is an experimental API and is not supported in every browser. + if ('connection' in navigator) { + const connection = (navigator as any).connection; + // Don't prefetch if Save-Data is enabled. + if (connection.saveData) { return Promise.reject(new Error('Cannot prefetch, Save-Data is enabled')); } - if (/2g/.test(conn.effectiveType)) { + + // Do not prefetch if using 2G or 3G + if (/(2|3)g/.test(connection.effectiveType)) { return Promise.reject(new Error('Cannot prefetch, network conditions are poor')); } } @@ -109,12 +115,8 @@ export default function prefetch({ }); requestIdleCallback(() => { - const links = Array.from(document.querySelectorAll(selector)).filter( - shouldPreload - ); - - for (const link of links) { - observe(link); - } + const links = [...document.querySelectorAll(selector)] + .filter(shouldPreload); + links.forEach(observe); }); } diff --git a/packages/integrations/prefetch/src/index.ts b/packages/integrations/prefetch/src/index.ts index cb1c73a0b..74ec5186e 100644 --- a/packages/integrations/prefetch/src/index.ts +++ b/packages/integrations/prefetch/src/index.ts @@ -5,7 +5,7 @@ export default function (options: PrefetchOptions = {}): AstroIntegration { return { name: '@astrojs/prefetch', hooks: { - 'astro:config:setup': ({ updateConfig, addRenderer, injectScript }) => { + 'astro:config:setup': ({ injectScript }) => { // Inject the necessary polyfills on every page (inlined for speed). injectScript( 'page',