Improve prefetch conditions (#5244)

* Improve prefetch

* Add changeset
This commit is contained in:
Robin Lindner 2022-11-01 13:42:30 +01:00 committed by GitHub
parent 2f8c9a98cc
commit 6ad91bd80d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 17 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/prefetch': patch
---
Do not prefetch if browser is offline or uses 3G

View file

@ -15,7 +15,7 @@ function shouldPreload({ href }: { href: string }) {
window.location.pathname !== url.pathname && window.location.pathname !== url.pathname &&
!preloaded.has(href) !preloaded.has(href)
); );
} catch {} } catch { }
return false; return false;
} }
@ -44,12 +44,11 @@ function onLinkEvent({ target }: Event) {
async function preloadHref(link: HTMLAnchorElement) { async function preloadHref(link: HTMLAnchorElement) {
unobserve(link); unobserve(link);
const { href } = link; const { href } = link;
try { try {
const contents = await fetch(href).then((res) => res.text()); const contents = await fetch(href).then((res) => res.text());
parser = parser || new DOMParser(); parser ||= new DOMParser();
const html = parser.parseFromString(contents, 'text/html'); const html = parser.parseFromString(contents, 'text/html');
const styles = Array.from(html.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]')); const styles = Array.from(html.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]'));
@ -62,7 +61,7 @@ async function preloadHref(link: HTMLAnchorElement) {
return fetch(el.href); return fetch(el.href);
}) })
); );
} catch {} } catch { }
} }
export interface PrefetchOptions { export interface PrefetchOptions {
@ -84,14 +83,21 @@ export default function prefetch({
selector = 'a[href][rel~="prefetch"]', selector = 'a[href][rel~="prefetch"]',
throttle = 1, throttle = 1,
}: PrefetchOptions) { }: 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') { // `Navigator.connection` is an experimental API and is not supported in every browser.
// Don't prefetch if using 2G or if Save-Data is enabled. if ('connection' in navigator) {
if (conn.saveData) { 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')); 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')); return Promise.reject(new Error('Cannot prefetch, network conditions are poor'));
} }
} }
@ -109,12 +115,8 @@ export default function prefetch({
}); });
requestIdleCallback(() => { requestIdleCallback(() => {
const links = Array.from(document.querySelectorAll<HTMLAnchorElement>(selector)).filter( const links = [...document.querySelectorAll<HTMLAnchorElement>(selector)]
shouldPreload .filter(shouldPreload);
); links.forEach(observe);
for (const link of links) {
observe(link);
}
}); });
} }

View file

@ -5,7 +5,7 @@ export default function (options: PrefetchOptions = {}): AstroIntegration {
return { return {
name: '@astrojs/prefetch', name: '@astrojs/prefetch',
hooks: { hooks: {
'astro:config:setup': ({ updateConfig, addRenderer, injectScript }) => { 'astro:config:setup': ({ injectScript }) => {
// Inject the necessary polyfills on every page (inlined for speed). // Inject the necessary polyfills on every page (inlined for speed).
injectScript( injectScript(
'page', 'page',