Skip to content

Commit d9bbf66

Browse files
authored
fix: make prerender cache work, including in dev (#14860)
* fix: make prerender cache work * populate cache on startup * lint
1 parent d37f9df commit d9bbf66

File tree

6 files changed

+50
-28
lines changed

6 files changed

+50
-28
lines changed

.changeset/tender-rings-hammer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: make prerender cache work, including in development

packages/kit/src/core/sync/write_client_manifest.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export function write_client_manifest(kit, manifest_data, output, metadata) {
171171
};
172172
173173
export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode]));
174+
export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode]));
174175
175176
export const hash = ${s(kit.router.type === 'hash')};
176177

packages/kit/src/runtime/client/remote-functions/prerender.svelte.js

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/** @import { RemoteFunctionResponse } from 'types' */
21
import { app_dir, base } from '$app/paths/internal/client';
32
import { version } from '__sveltekit/environment';
43
import * as devalue from 'devalue';
@@ -7,12 +6,12 @@ import { app, remote_responses } from '../client.js';
76
import { create_remote_function, remote_request } from './shared.svelte.js';
87

98
// Initialize Cache API for prerender functions
10-
const CACHE_NAME = `sveltekit:${version}`;
9+
const CACHE_NAME = DEV ? `sveltekit:${Date.now()}` : `sveltekit:${version}`;
1110
/** @type {Cache | undefined} */
1211
let prerender_cache;
1312

14-
void (async () => {
15-
if (!DEV && typeof caches !== 'undefined') {
13+
const prerender_cache_ready = (async () => {
14+
if (typeof caches !== 'undefined') {
1615
try {
1716
prerender_cache = await caches.open(CACHE_NAME);
1817

@@ -111,53 +110,68 @@ class Prerender {
111110
}
112111
}
113112

113+
/**
114+
* @param {string} url
115+
* @param {string} encoded
116+
*/
117+
function put(url, encoded) {
118+
return /** @type {Cache} */ (prerender_cache)
119+
.put(
120+
url,
121+
// We need to create a new response because the original response is already consumed
122+
new Response(encoded, {
123+
headers: {
124+
'Content-Type': 'application/json'
125+
}
126+
})
127+
)
128+
.catch(() => {
129+
// Nothing we can do here
130+
});
131+
}
132+
114133
/**
115134
* @param {string} id
116135
*/
117136
export function prerender(id) {
118137
return create_remote_function(id, (cache_key, payload) => {
119138
return new Prerender(async () => {
120-
if (Object.hasOwn(remote_responses, cache_key)) {
121-
return remote_responses[cache_key];
122-
}
139+
await prerender_cache_ready;
123140

124141
const url = `${base}/${app_dir}/remote/${id}${payload ? `/${payload}` : ''}`;
125142

143+
if (Object.hasOwn(remote_responses, cache_key)) {
144+
const data = remote_responses[cache_key];
145+
146+
if (prerender_cache) {
147+
void put(url, devalue.stringify(data, app.encoders));
148+
}
149+
150+
return data;
151+
}
152+
126153
// Check the Cache API first
127154
if (prerender_cache) {
128155
try {
129156
const cached_response = await prerender_cache.match(url);
157+
130158
if (cached_response) {
131-
const cached_result = /** @type { RemoteFunctionResponse & { type: 'result' } } */ (
132-
await cached_response.json()
133-
);
134-
return devalue.parse(cached_result.result, app.decoders);
159+
const cached_result = await cached_response.text();
160+
return devalue.parse(cached_result, app.decoders);
135161
}
136162
} catch {
137163
// Nothing we can do here
138164
}
139165
}
140166

141-
const result = await remote_request(url);
167+
const encoded = await remote_request(url);
142168

143169
// For successful prerender requests, save to cache
144170
if (prerender_cache) {
145-
try {
146-
await prerender_cache.put(
147-
url,
148-
// We need to create a new response because the original response is already consumed
149-
new Response(JSON.stringify(result), {
150-
headers: {
151-
'Content-Type': 'application/json'
152-
}
153-
})
154-
);
155-
} catch {
156-
// Nothing we can do here
157-
}
171+
void put(url, encoded);
158172
}
159173

160-
return result;
174+
return devalue.parse(encoded, app.decoders);
161175
});
162176
});
163177
}

packages/kit/src/runtime/client/remote-functions/query.svelte.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export function query(id) {
3131

3232
const url = `${base}/${app_dir}/remote/${id}${payload ? `?payload=${payload}` : ''}`;
3333

34-
return await remote_request(url);
34+
const result = await remote_request(url);
35+
return devalue.parse(result, app.decoders);
3536
});
3637
});
3738
}

packages/kit/src/runtime/client/remote-functions/shared.svelte.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export async function remote_request(url) {
3737
throw new HttpError(result.status ?? 500, result.error);
3838
}
3939

40-
return devalue.parse(result.result, app.decoders);
40+
return result.result;
4141
}
4242

4343
/**

packages/kit/src/runtime/client/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface SvelteKitApp {
5050
decode: (type: string, value: any) => any;
5151

5252
decoders: Record<string, (data: any) => any>;
53+
encoders: Record<string, (data: any) => any>;
5354

5455
/**
5556
* Whether or not we're using hash-based routing

0 commit comments

Comments
 (0)