summaryrefslogtreecommitdiff
path: root/packages/integrations/prefetch/src
diff options
context:
space:
mode:
authorGravatar Kory Smith <kor54e@gmail.com> 2023-07-07 16:01:23 -0400
committerGravatar GitHub <noreply@github.com> 2023-07-07 16:01:23 -0400
commit9807e4dc22355f0b3b2ff65b0724a95af8e9702d (patch)
tree723c86670761f97a1bc7b89141521a740e37aff8 /packages/integrations/prefetch/src
parentc135633bf6a84e751249920cba9009f0e394e29a (diff)
downloadastro-9807e4dc22355f0b3b2ff65b0724a95af8e9702d.tar.gz
astro-9807e4dc22355f0b3b2ff65b0724a95af8e9702d.tar.zst
astro-9807e4dc22355f0b3b2ff65b0724a95af8e9702d.zip
Updates prefetch integration to add "only prefetch link on hover/mouseover/focus" option (#6585)
* modifies prefetch to add the option to only prefetch certain pages on hover * adds new pages to the test website to showcase prefetch-intent functionality * adds tests to verify prefetch-intent behavior * adds changelog * waits until networkidle to check if the prefetching worked instead of waiting on a specific url load * allows intentSelector to be either a string or array of strings * Revert "allows intentSelector to be either a string or array of strings" This reverts commit b0268eb0d5220ad2b08b0b7aee23f43e4caf879f. * fixes the multiple selector logic and adds tests * updates docs to include new prefetch-intent integration * Update packages/integrations/prefetch/README.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update packages/integrations/prefetch/README.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update packages/integrations/prefetch/README.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update .changeset/little-cars-exist.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update packages/integrations/prefetch/README.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> --------- Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com> Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
Diffstat (limited to 'packages/integrations/prefetch/src')
-rw-r--r--packages/integrations/prefetch/src/client.ts36
1 files changed, 35 insertions, 1 deletions
diff --git a/packages/integrations/prefetch/src/client.ts b/packages/integrations/prefetch/src/client.ts
index a8b88d85c..dc05cb84b 100644
--- a/packages/integrations/prefetch/src/client.ts
+++ b/packages/integrations/prefetch/src/client.ts
@@ -77,11 +77,18 @@ export interface PrefetchOptions {
* @default 1
*/
throttle?: number;
+ /**
+ * Element selector used to find all links on the page that should be prefetched on user interaction.
+ *
+ * @default 'a[href][rel~="prefetch-intent"]'
+ */
+ intentSelector?: string | string[];
}
export default function prefetch({
selector = 'a[href][rel~="prefetch"]',
throttle = 1,
+ intentSelector = 'a[href][rel~="prefetch-intent"]',
}: PrefetchOptions) {
// If the navigator is offline, it is very unlikely that a request can be made successfully
if (!navigator.onLine) {
@@ -109,7 +116,21 @@ export default function prefetch({
new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && entry.target instanceof HTMLAnchorElement) {
- toAdd(() => preloadHref(entry.target as HTMLAnchorElement).finally(isDone));
+ const relAttributeValue = entry.target.getAttribute('rel') || '';
+ let matchesIntentSelector = false;
+ // Check if intentSelector is an array
+ if (Array.isArray(intentSelector)) {
+ // If intentSelector is an array, use .some() to check for matches
+ matchesIntentSelector = intentSelector.some((intent) =>
+ relAttributeValue.includes(intent)
+ );
+ } else {
+ // If intentSelector is a string, use .includes() to check for a match
+ matchesIntentSelector = relAttributeValue.includes(intentSelector);
+ }
+ if (!matchesIntentSelector) {
+ toAdd(() => preloadHref(entry.target as HTMLAnchorElement).finally(isDone));
+ }
}
});
});
@@ -117,5 +138,18 @@ export default function prefetch({
requestIdleCallback(() => {
const links = [...document.querySelectorAll<HTMLAnchorElement>(selector)].filter(shouldPreload);
links.forEach(observe);
+
+ const intentSelectorFinal = Array.isArray(intentSelector)
+ ? intentSelector.join(',')
+ : intentSelector;
+ // Observe links with prefetch-intent
+ const intentLinks = [
+ ...document.querySelectorAll<HTMLAnchorElement>(intentSelectorFinal),
+ ].filter(shouldPreload);
+ intentLinks.forEach((link) => {
+ events.map((event) =>
+ link.addEventListener(event, onLinkEvent, { passive: true, once: true })
+ );
+ });
});
}