0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

Fallback to tap prefetch strategy on slow connection (#9092)

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
This commit is contained in:
Smit Barmase 2023-11-22 18:40:09 +05:30 committed by GitHub
parent 0970fd635c
commit 0ea4bd47e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 9 deletions

View file

@ -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.

View file

@ -0,0 +1,5 @@
---
'astro': minor
---
Adds a `ignoreSlowConnection` option to the `prefetch()` API to prefetch even on data saver mode or slow connection.

View file

@ -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 }
@ -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;
}
/**
@ -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';
@ -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);
@ -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 === '') {
@ -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
*/