-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathclient.tsx
More file actions
78 lines (71 loc) · 2.49 KB
/
client.tsx
File metadata and controls
78 lines (71 loc) · 2.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
'use client-entry';
import {fetchRSC, hydrate} from '@parcel/rsc/client';
import type {ReactElement} from 'react';
// Hydrate initial RSC payload embedded in the HTML.
let updateRoot = hydrate({
// Intercept HMR window reloads, and do it with RSC instead.
onHmrReload() {
navigate(location.pathname + location.search + location.hash);
}
});
// A very simple router. When we navigate, we'll fetch a new RSC payload from the server,
// and in a React transition, stream in the new page. Once complete, we'll pushState to
// update the URL in the browser.
async function navigate(pathname: string, push = false) {
try {
let res = await fetchRSC<ReactElement>(pathname.replace('.html', '.rsc'));
let currentPath = location.pathname;
let [newBasePath, newPathAnchor] = pathname.split('#');
updateRoot(res, () => {
if (push) {
history.pushState(null, '', pathname);
push = false;
}
// Reset scroll if navigating to a different page without an anchor
if (currentPath !== newBasePath && !newPathAnchor) {
window.scrollTo(0, 0);
} else if (newPathAnchor) {
let element = document.getElementById(newPathAnchor);
if (element) {
element.scrollIntoView();
}
}
});
} catch {
let errorRes = await fetchRSC<ReactElement>('/error.rsc');
updateRoot(errorRes, () => {
if (push) {
history.pushState(null, '', '/error.html');
}
});
}
}
// Intercept link clicks to perform RSC navigation.
document.addEventListener('click', e => {
let link = (e.target as Element).closest('a');
let publicUrl = process.env.PUBLIC_URL || '/';
let publicUrlPathname = publicUrl.startsWith('http') ? new URL(publicUrl).pathname : publicUrl;
if (
link &&
link instanceof HTMLAnchorElement &&
link.href &&
(!link.target || link.target === '_self') &&
link.origin === location.origin &&
link.pathname !== location.pathname &&
!link.hasAttribute('download') &&
link.pathname.startsWith(publicUrlPathname) &&
e.button === 0 && // left clicks only
!e.metaKey && // open in new tab (mac)
!e.ctrlKey && // open in new tab (windows)
!e.altKey && // download
!e.shiftKey &&
!e.defaultPrevented
) {
e.preventDefault();
navigate(link.pathname + link.search + link.hash, true);
}
});
// When the user clicks the back button, navigate with RSC.
window.addEventListener('popstate', () => {
navigate(location.pathname + location.search + location.hash);
});