Skip to content

Commit 8871b54

Browse files
authored
fix: preload links if href changes (#15191)
* test * fix * changeset
1 parent e5627ef commit 8871b54

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

.changeset/small-coins-show.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: preload links if href changes

packages/kit/src/runtime/client/client.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,8 +1860,8 @@ if (import.meta.hot) {
18601860
function setup_preload() {
18611861
/** @type {NodeJS.Timeout} */
18621862
let mousemove_timeout;
1863-
/** @type {Element} */
1864-
let current_a;
1863+
/** @type {{ element: Element | SVGAElement | undefined; href: string | SVGAnimatedString | undefined }} */
1864+
let current_a = { element: undefined, href: undefined };
18651865
/** @type {PreloadDataPriority} */
18661866
let current_priority;
18671867

@@ -1903,7 +1903,8 @@ function setup_preload() {
19031903
const a = find_anchor(element, container);
19041904

19051905
// we don't want to preload data again if the user has already hovered/tapped
1906-
const interacted = a === current_a && priority >= current_priority;
1906+
const interacted =
1907+
a === current_a.element && a?.href === current_a.href && priority >= current_priority;
19071908
if (!a || interacted) return;
19081909

19091910
const { url, external, download } = get_link_info(a, base, app.hash);
@@ -1916,7 +1917,7 @@ function setup_preload() {
19161917
if (options.reload || same_url) return;
19171918

19181919
if (priority <= options.preload_data) {
1919-
current_a = a;
1920+
current_a = { element: a, href: a.href };
19201921
// we don't want to preload data again on tap if we've already preloaded it on hover
19211922
current_priority = PRELOAD_PRIORITIES.tap;
19221923

@@ -1938,7 +1939,7 @@ function setup_preload() {
19381939
void _preload_data(intent);
19391940
}
19401941
} else if (priority <= options.preload_code) {
1941-
current_a = a;
1942+
current_a = { element: a, href: a.href };
19421943
current_priority = priority;
19431944
void _preload_code(/** @type {URL} */ (url));
19441945
}

packages/kit/test/apps/basics/src/routes/data-sveltekit/preload-data/+page.svelte

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<script>
2+
let x = 0;
3+
</script>
4+
15
<a id="one" href="/data-sveltekit/preload-data/target" data-sveltekit-preload-data>one</a>
26

37
<div data-sveltekit-preload-data>
@@ -15,3 +19,8 @@
1519
data-sveltekit-preload-code="hover"
1620
data-sveltekit-preload-data="tap">hover for code then tap for data</a
1721
>
22+
23+
<a id="dynamic" data-sveltekit-preload-data="hover" href="/data-sveltekit/preload-data/target?x={x}"
24+
>dynamic</a
25+
>
26+
<button id="change_dynamic" type="button" on:click={() => x++}>change dynamic</button>

packages/kit/test/apps/basics/test/client.test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,33 @@ test.describe('data-sveltekit attributes', () => {
979979
page.waitForLoadState('networkidle') // wait for preloading to finish
980980
]);
981981
expect(requests.length).toBe(2);
982+
983+
requests.length = 0;
984+
await page.goto('/data-sveltekit/preload-data');
985+
await page.locator('#dynamic').hover();
986+
await page.locator('#dynamic').dispatchEvent('touchstart');
987+
await Promise.all([
988+
page.waitForTimeout(100), // wait for preloading to start
989+
page.waitForLoadState('networkidle') // wait for preloading to finish
990+
]);
991+
expect(requests.length).toBe(2);
992+
await page.waitForTimeout(100);
993+
await page.locator('#dynamic').hover();
994+
await page.locator('#dynamic').dispatchEvent('touchstart');
995+
await Promise.all([
996+
page.waitForTimeout(100), // wait for preloading to start
997+
page.waitForLoadState('networkidle') // wait for preloading to finish
998+
]);
999+
expect(requests.length).toBe(2);
1000+
await page.locator('#change_dynamic').click();
1001+
await page.waitForTimeout(100);
1002+
await page.locator('#dynamic').hover();
1003+
await page.locator('#dynamic').dispatchEvent('touchstart');
1004+
await Promise.all([
1005+
page.waitForTimeout(100), // wait for preloading to start
1006+
page.waitForLoadState('networkidle') // wait for preloading to finish
1007+
]);
1008+
expect(requests.length).toBe(3);
9821009
});
9831010

9841011
test('data-sveltekit-preload-data network failure does not trigger navigation', async ({

0 commit comments

Comments
 (0)