Skip to content

Commit

Permalink
Fallback to tap prefetch strategy on slow connection (#9092)
Browse files Browse the repository at this point in the history
Co-authored-by: Sarah Rainsberger <[email protected]>
Co-authored-by: Bjorn Lu <[email protected]>
  • Loading branch information
3 people authored Nov 22, 2023
1 parent 0970fd6 commit 0ea4bd4
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/neat-mangos-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': minor
---

Changes the fallback prefetch behavior on slow connections and when data saver mode is enabled. Instead of disabling prefetch entirely, the `tap` strategy will be used.
5 changes: 5 additions & 0 deletions .changeset/six-owls-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': minor
---

Adds a `ignoreSlowConnection` option to the `prefetch()` API to prefetch even on data saver mode or slow connection.
34 changes: 25 additions & 9 deletions packages/astro/src/prefetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function initTapStrategy() {
event,
(e) => {
if (elMatchesStrategy(e.target, 'tap')) {
prefetch(e.target.href, { with: 'fetch' });
prefetch(e.target.href, { with: 'fetch', ignoreSlowConnection: true });
}
},
{ passive: true }
Expand Down Expand Up @@ -176,6 +176,10 @@ export interface PrefetchOptions {
* - `'fetch'`: use `fetch()`, has higher loading priority.
*/
with?: 'link' | 'fetch';
/**
* Should prefetch even on data saver mode or slow connection. (default `false`)
*/
ignoreSlowConnection?: boolean;
}

/**
Expand All @@ -190,7 +194,8 @@ export interface PrefetchOptions {
* @param opts Additional options for prefetching.
*/
export function prefetch(url: string, opts?: PrefetchOptions) {
if (!canPrefetchUrl(url)) return;
const ignoreSlowConnection = opts?.ignoreSlowConnection ?? false;
if (!canPrefetchUrl(url, ignoreSlowConnection)) return;
prefetchedUrls.add(url);

const priority = opts?.with ?? 'link';
Expand All @@ -211,15 +216,11 @@ export function prefetch(url: string, opts?: PrefetchOptions) {
}
}

function canPrefetchUrl(url: string) {
function canPrefetchUrl(url: string, ignoreSlowConnection: boolean) {
// Skip prefetch if offline
if (!navigator.onLine) return false;
if ('connection' in navigator) {
// Untyped Chrome-only feature: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
const conn = navigator.connection as any;
// Skip prefetch if using data saver mode or slow connection
if (conn.saveData || /(2|3)g/.test(conn.effectiveType)) return false;
}
// Skip prefetch if using data saver mode or slow connection
if (!ignoreSlowConnection && isSlowConnection()) return false;
// Else check if URL is within the same origin, not the current page, and not already prefetched
try {
const urlObj = new URL(url, location.href);
Expand All @@ -241,6 +242,12 @@ function elMatchesStrategy(el: EventTarget | null, strategy: string): el is HTML
if (attrValue === 'false') {
return false;
}

// Fallback to tap strategy if using data saver mode or slow connection
if (strategy === 'tap' && (attrValue != null || prefetchAll) && isSlowConnection()) {
return true;
}

// If anchor has no dataset but we want to prefetch all, or has dataset but no value,
// check against fallback default strategy
if ((attrValue == null && prefetchAll) || attrValue === '') {
Expand All @@ -254,6 +261,15 @@ function elMatchesStrategy(el: EventTarget | null, strategy: string): el is HTML
return false;
}

function isSlowConnection() {
if ('connection' in navigator) {
// Untyped Chrome-only feature: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
const conn = navigator.connection as any;
return conn.saveData || /(2|3)g/.test(conn.effectiveType);
}
return false;
}

/**
* Listen to page loads and handle Astro's View Transition specific events
*/
Expand Down

0 comments on commit 0ea4bd4

Please sign in to comment.