Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Commit

Permalink
Fix prefetching when clicking quickly back and forth (#1668)
Browse files Browse the repository at this point in the history
  • Loading branch information
ehrencrona authored Dec 14, 2020
1 parent 13b1243 commit 4a32dec
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 19 deletions.
43 changes: 24 additions & 19 deletions runtime/src/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,29 +236,34 @@ export async function hydrate_target(dest: Target): Promise<HydratedTarget> {

const j = l++;

if (!session_dirty && !segment_dirty && current_branch[i] && current_branch[i].part === part.i) {
return current_branch[i];
}

segment_dirty = false;
let result;

const { default: component, preload } = await components[part.i].js();

let preloaded: object;
if (ready || !initial_data.preloaded[i + 1]) {
preloaded = preload
? await preload.call(preload_context, {
host: page.host,
path: page.path,
query: page.query,
params: part.params ? part.params(dest.match) : {}
}, $session)
: {};
if (!session_dirty && !segment_dirty && current_branch[i] && current_branch[i].part === part.i) {
result = current_branch[i];
} else {
preloaded = initial_data.preloaded[i + 1];
segment_dirty = false;

const { default: component, preload } = await components[part.i].js();

let preloaded: object;

if (ready || !initial_data.preloaded[i + 1]) {
preloaded = preload
? await preload.call(preload_context, {
host: page.host,
path: page.path,
query: page.query,
params: part.params ? part.params(dest.match) : {}
}, $session)
: {};
} else {
preloaded = initial_data.preloaded[i + 1];
}

result = { component, props: preloaded, segment, match, part: part.i };
}

return (props[`level${j}`] = { component, props: preloaded, segment, match, part: part.i });
return (props[`level${j}`] = result);
}));
} catch (error) {
props.error = error;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script context="module">
export function preload() {
if (typeof window !== 'undefined' && window.onPrefetched) {
Promise.resolve().then(() => window.onPrefetched());
}
}
</script>

<script>
import { onMount } from 'svelte';
let prefetchlink;
onMount(() => {
let timeout;
/**
* This emulates the logic in start prefetching. Just firing after the first mouse move
* would also work fine in the Puppeteer tests, just not if you try it manually.
*/
prefetchlink.addEventListener('mousemove', () => {
clearTimeout(timeout);
if (window.onPrefetched) {
timeout = setTimeout(() => {
window.onPrefetched();
}, 50);
}
});
});
</script>

<h1>Prefetched</h1>

<a href="/prefetch-timing/prefetcher">prefetcher</a>
<a href="/prefetch-timing/prefetched" rel="prefetch" bind:this={prefetchlink}>prefetched</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script context="module">
export function preload() {
if (typeof window !== 'undefined') {
return new Promise((resolve) => {
window.onPrefetched = resolve;
});
}
}
</script>

<h1>Prefetcher</h1>

<a href="/prefetch-timing/prefetched" rel="prefetch">prefetched</a>
30 changes: 30 additions & 0 deletions test/apps/basics/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,36 @@ describe('basics', function() {
assert.equal(await r.text('h2'), 'Called 1 time');
});

/**
* Before a page navigation finishes, hover over a prefetching link back to the page we came from.
* Prefetching starts, but we're still on the page being preloaded!
* After that happened, clicking on the link back to the original page did not work.
* https://github.com/sveltejs/sapper/issues/1667
*/
it('handles prefetching to the current page', async () => {
await r.load('/prefetch-timing/prefetched');
await r.sapper.start();
await r.sapper.prefetchRoutes();

assert.strictEqual(await r.text('h1'), 'Prefetched');

const prefetchedSelector = 'a[href="/prefetch-timing/prefetched"]';
const prefetcherSelector = 'a[href="/prefetch-timing/prefetcher"]';

await r.page.click(prefetcherSelector);
await r.wait();

await r.page.hover(prefetchedSelector);
await r.wait(50);

await r.page.waitForFunction(() => document.querySelector('h1').innerHTML == 'Prefetcher');

await r.page.click(prefetchedSelector);
await r.wait();

assert.strictEqual(await r.text('h1'), 'Prefetched');
});

it('survives the tests with no server errors', () => {
assert.deepEqual(r.errors, []);
});
Expand Down

0 comments on commit 4a32dec

Please sign in to comment.