Skip to content

Commit 2f1fa18

Browse files
committed
improve anchor preload performance
1 parent dc27730 commit 2f1fa18

File tree

2 files changed

+21
-34
lines changed

2 files changed

+21
-34
lines changed

.changeset/tidy-kiwis-tickle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@solidjs/router": patch
3+
---
4+
5+
improve anchor preload performance

src/data/events.ts

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ export function setupNativeEvents(
1313
return (router: RouterContext) => {
1414
const basePath = router.base.path();
1515
const navigateFromRoute = router.navigatorFactory(router.base);
16-
let preloadTimeout: Record<string, number> = {};
16+
let preloadTimeout: string;
17+
let lastElement: Node | null;
1718

1819
function isSvg<T extends SVGElement>(el: T | HTMLElement): el is T {
1920
return el.namespaceURI === "http://www.w3.org/2000/svg";
@@ -76,38 +77,21 @@ export function setupNativeEvents(
7677
const res = handleAnchor(evt as MouseEvent);
7778
if (!res) return;
7879
const [a, url] = res;
79-
if (typeof transformUrl === "function") {
80-
url.pathname = transformUrl(url.pathname);
81-
}
82-
if (!preloadTimeout[url.pathname])
83-
router.preloadRoute(url, { preloadData: a.getAttribute("preload") !== "false" });
80+
transformUrl && (url.pathname = transformUrl(url.pathname));
81+
router.preloadRoute(url, { preloadData: a.getAttribute("preload") !== "false" });
8482
}
8583

86-
function handleAnchorIn(evt: Event) {
84+
function handleAnchorMove(evt: Event) {
85+
clearTimeout(preloadTimeout)
8786
const res = handleAnchor(evt as MouseEvent);
88-
if (!res) return;
87+
if (!res) return lastElement = null;
8988
const [a, url] = res;
90-
if (typeof transformUrl === "function") {
91-
url.pathname = transformUrl(url.pathname);
92-
}
93-
if (preloadTimeout[url.pathname]) return;
94-
preloadTimeout[url.pathname] = setTimeout(() => {
89+
if (lastElement === a) return;
90+
transformUrl && (url.pathname = transformUrl(url.pathname));
91+
preloadTimeout = setTimeout(() => {
9592
router.preloadRoute(url, { preloadData: a.getAttribute("preload") !== "false" });
96-
delete preloadTimeout[url.pathname];
97-
}, 200) as any;
98-
}
99-
100-
function handleAnchorOut(evt: Event) {
101-
const res = handleAnchor(evt as MouseEvent);
102-
if (!res) return;
103-
const [, url] = res;
104-
if (typeof transformUrl === "function") {
105-
url.pathname = transformUrl(url.pathname);
106-
}
107-
if (preloadTimeout[url.pathname]) {
108-
clearTimeout(preloadTimeout[url.pathname]);
109-
delete preloadTimeout[url.pathname];
110-
}
93+
lastElement = a;
94+
}, 20) as any;
11195
}
11296

11397
function handleFormSubmit(evt: SubmitEvent) {
@@ -142,17 +126,15 @@ export function setupNativeEvents(
142126
delegateEvents(["click", "submit"]);
143127
document.addEventListener("click", handleAnchorClick);
144128
if (preload) {
145-
document.addEventListener("mouseover", handleAnchorIn);
146-
document.addEventListener("mouseout", handleAnchorOut);
147-
document.addEventListener("focusin", handleAnchorPreload);
148-
document.addEventListener("touchstart", handleAnchorPreload);
129+
document.addEventListener("mousemove", handleAnchorMove, { passive: true });
130+
document.addEventListener("focusin", handleAnchorPreload, { passive: true });
131+
document.addEventListener("touchstart", handleAnchorPreload, { passive: true });
149132
}
150133
document.addEventListener("submit", handleFormSubmit);
151134
onCleanup(() => {
152135
document.removeEventListener("click", handleAnchorClick);
153136
if (preload) {
154-
document.removeEventListener("mouseover", handleAnchorIn);
155-
document.removeEventListener("mouseout", handleAnchorOut);
137+
document.removeEventListener("mousemove", handleAnchorMove);
156138
document.removeEventListener("focusin", handleAnchorPreload);
157139
document.removeEventListener("touchstart", handleAnchorPreload);
158140
}

0 commit comments

Comments
 (0)