Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .changeset/poor-squids-like.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
'astro': minor
---

Add `eagerness` support for `prefetch()`

With [`clientPrerender`](https://docs.astro.build/en/reference/experimental-flags/client-prerender/) experiment enabled, you can use `eagerness` option, following the same API described in [Speculation Rules API](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/speculationrules#eagerness).

For example, you have a set of links that you want to be prerendered/prefetched but there are too many for browsers to handle (Chrome have some [limits in place](https://developer.chrome.com/blog/speculation-rules-improvements#chrome-limits)).
To prevent that, you can set `eagerness: 'moderate'` to get advantage of FIFO strategies and browser heuristics to let it decide when prerender/prefetch them and in what order.

```astro
<a class="link-moderate" href="/nice-link-1">A Nice Link 1</a>
<a class="link-moderate" href="/nice-link-2">A Nice Link 2</a>
<a class="link-moderate" href="/nice-link-3">A Nice Link 3</a>
<a class="link-moderate" href="/nice-link-4">A Nice Link 4</a>
...
<a class="link-moderate" href="/nice-link-20">A Nice Link 20</a>
<script>
import { prefetch } from 'astro:prefetch';
const linkModerate = document.getElementsByClassName('link-moderate');
linkModerate.forEach((link) => prefetch(link.getAttribute('href'), {eagerness: 'moderate'}));

</script>
```
16 changes: 14 additions & 2 deletions packages/astro/src/prefetch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ export interface PrefetchOptions {
* Should prefetch even on data saver mode or slow connection. (default `false`)
*/
ignoreSlowConnection?: boolean;
/**
* A string providing a hint to the browser as to how eagerly it should prefetch/prerender link targets in order to balance performance advantages against resource overheads. (default `immediate`)
* Only works if `clientPrerender` is enabled and browser supports Speculation Rules API.
* The browser takes this hint into consideration along with its own heuristics, so it may select a link that the author has hinted as less eager than another, if the less eager candidate is considered a better choice.
*
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/speculationrules#eagerness
*/
eagerness?: 'immediate' | 'eager' | 'moderate' | 'conservative';
}

/**
Expand All @@ -225,7 +233,7 @@ export function prefetch(url: string, opts?: PrefetchOptions) {
// NOTE: This condition is tree-shaken if `clientPrerender` is false as its a static value
if (clientPrerender && HTMLScriptElement.supports?.('speculationrules')) {
debug?.(`[astro] Prefetching ${url} with <script type="speculationrules">`);
appendSpeculationRules(url);
appendSpeculationRules(url, opts?.eagerness ?? 'immediate');
}
// Prefetch with link if supported
else if (
Expand Down Expand Up @@ -324,15 +332,18 @@ function onPageLoad(cb: () => void) {
* A new script must be added for each `url`.
*
* @param url The url of the page to prerender.
*
* @param eagerness Hint to the browser as to how eagerly it should prefetch/prerender link targets
*/
function appendSpeculationRules(url: string) {
function appendSpeculationRules(url: string, eagerness: PrefetchOptions["eagerness"]) {
const script = document.createElement('script');
script.type = 'speculationrules';
script.textContent = JSON.stringify({
prerender: [
{
source: 'list',
urls: [url],
eagerness: eagerness,
},
],
// Currently, adding `prefetch` is required to fallback if `prerender` fails.
Expand All @@ -342,6 +353,7 @@ function appendSpeculationRules(url: string) {
{
source: 'list',
urls: [url],
eagerness: eagerness,
},
],
});
Expand Down