Skip to content

Commit 7fa131f

Browse files
authored
feat: add link preloading (#20)
1 parent 4b31733 commit 7fa131f

File tree

5 files changed

+38
-2
lines changed

5 files changed

+38
-2
lines changed

.changeset/sharp-roses-look.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'sv-router': patch
3+
---
4+
5+
Add link preloading

examples/file-based/src/App.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55

66
<a href={path('/')}>Home</a>
77
<a href={path('/about')}>About</a>
8-
<a href={path('/posts')}>Posts</a>
8+
<a href={path('/posts')} data-preload>Posts</a>
99
<button onclick={() => goto('/posts/:id', { id: 'programmatic' })}>Programmatic</button>
1010
<Router />

examples/file-based/src/routes/posts/index.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
<h1>Posts</h1>
44
<a href="/posts/hello-world">Hello world</a>
5-
<a href="/posts/foobar">Foo bar</a>
5+
<a href="/posts/foobar" data-preload>Foo bar</a>

src/create-router.svelte.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BROWSER, DEV } from 'esm-env';
22
import { matchRoute } from './helpers/match-route.js';
3+
import { preloadOnHover } from './helpers/preload-on-hover.js';
34
import { constructPath, resolveRouteComponents } from './helpers/utils.js';
45

56
/** @type {import('./index.d.ts').Routes} */
@@ -25,6 +26,8 @@ export function createRouter(r) {
2526
});
2627
}
2728

29+
preloadOnHover(routes);
30+
2831
return {
2932
path: constructPath,
3033
goto(...args) {

src/helpers/preload-on-hover.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { matchRoute } from './match-route.js';
2+
import { resolveRouteComponents } from './utils.js';
3+
4+
const linkSet = new Set();
5+
6+
/** @param {import('../index.d.ts').Routes} routes */
7+
export function preloadOnHover(routes) {
8+
const observer = new MutationObserver(() => {
9+
const links = document.querySelectorAll('a[data-preload]');
10+
for (const link of links) {
11+
if (linkSet.has(link)) continue;
12+
linkSet.add(link);
13+
14+
link.addEventListener('mouseenter', function callback() {
15+
link.removeEventListener('mouseenter', callback);
16+
const href = link.getAttribute('href');
17+
if (!href) return;
18+
const { match, layouts } = matchRoute(href, routes);
19+
resolveRouteComponents(match ? [...layouts, match] : layouts);
20+
});
21+
}
22+
});
23+
24+
observer.observe(document.body, {
25+
subtree: true,
26+
childList: true,
27+
});
28+
}

0 commit comments

Comments
 (0)