Skip to content

Commit 22887d4

Browse files
committed
feat: Add local, fs-based fetch during prerender
1 parent 1a15550 commit 22887d4

File tree

4 files changed

+54
-0
lines changed

4 files changed

+54
-0
lines changed

demo/public/local-fetch-test.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Local fetch works

demo/src/components/LocalFetch.tsx

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useState } from "preact/hooks";
2+
3+
const cache = new Map();
4+
5+
async function load(url: string) {
6+
const res = await fetch(url);
7+
return await res.text();
8+
}
9+
10+
function useFetch(url: string) {
11+
const [_, update] = useState({});
12+
13+
let data = cache.get(url);
14+
if (!data) {
15+
data = load(url);
16+
cache.set(url, data);
17+
data.then(
18+
(res: string) => update((data.res = res)),
19+
(err: Error) => update((data.err = err)),
20+
);
21+
}
22+
23+
if (data.res) return data.res;
24+
if (data.err) throw data.err;
25+
throw data;
26+
}
27+
28+
export function LocalFetch() {
29+
const data = useFetch("/local-fetch-test.txt");
30+
31+
return <p>{data.trimEnd()}</p>;
32+
}

demo/src/pages/Home/index.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ReactComponent } from "../../components/Compat";
2+
import { LocalFetch } from "../../components/LocalFetch";
23

34
import preactLogo from "../../assets/preact.svg";
45
import "./style.css";
@@ -11,6 +12,7 @@ export function Home() {
1112
</a>
1213
<h1>Get Started building Vite-powered Preact Apps </h1>
1314
<ReactComponent />
15+
<LocalFetch />
1416
<section>
1517
<Resource
1618
title="Learn Preact"

src/prerender.ts

+19
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,25 @@ export function PrerenderPlugin({
149149
// @ts-ignore
150150
globalThis.self = globalThis;
151151

152+
// Local, fs-based fetch implementation for prerendering
153+
const nodeFetch = globalThis.fetch;
154+
// @ts-ignore
155+
globalThis.fetch = async (url: string, opts: RequestInit | undefined) => {
156+
if (/^\//.test(url)) {
157+
const text = () =>
158+
fs.readFile(
159+
`${path.join(
160+
viteConfig.root,
161+
viteConfig.build.outDir,
162+
)}/${url.replace(/^\//, "")}`,
163+
"utf-8",
164+
);
165+
return { text, json: () => text().then(JSON.parse) };
166+
}
167+
168+
return nodeFetch(url, opts);
169+
};
170+
152171
// Grab the generated HTML file, which we'll use as a template:
153172
const tpl = (bundle["index.html"] as OutputAsset).source as string;
154173
let htmlDoc = parse(tpl);

0 commit comments

Comments
 (0)