Skip to content

Commit b999cfd

Browse files
authored
fix: avoid running load functions when prerendering if no server load function exists and SSR is off (#11405)
1 parent 65b81de commit b999cfd

File tree

6 files changed

+34
-4
lines changed

6 files changed

+34
-4
lines changed

.changeset/orange-students-hide.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: render SPA shell when SSR is turned off and there is no server data

packages/kit/src/runtime/server/page/index.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function render_page(event, page, options, manifest, state, resolve
7272
}
7373
}
7474

75-
const should_prerender_data = nodes.some((node) => node?.server);
75+
const should_prerender_data = nodes.some((node) => node?.server?.load);
7676
const data_pathname = add_data_suffix(event.url.pathname);
7777

7878
// it's crucial that we do this before returning the non-SSR response, otherwise
@@ -98,7 +98,10 @@ export async function render_page(event, page, options, manifest, state, resolve
9898
/** @type {import('./types.js').Fetched[]} */
9999
const fetched = [];
100100

101-
if (get_option(nodes, 'ssr') === false && !state.prerendering) {
101+
// renders an empty 'shell' page if SSR is turned off and if there is
102+
// no server data to prerender. As a result, the load functions and rendering
103+
// only occur client-side.
104+
if (get_option(nodes, 'ssr') === false && !(state.prerendering && should_prerender_data)) {
102105
return await render_response({
103106
branch: [],
104107
fetched,
@@ -281,6 +284,8 @@ export async function render_page(event, page, options, manifest, state, resolve
281284
});
282285
}
283286

287+
const ssr = get_option(nodes, 'ssr') ?? true;
288+
284289
return await render_response({
285290
event,
286291
options,
@@ -289,11 +294,11 @@ export async function render_page(event, page, options, manifest, state, resolve
289294
resolve_opts,
290295
page_config: {
291296
csr: get_option(nodes, 'csr') ?? true,
292-
ssr: get_option(nodes, 'ssr') ?? true
297+
ssr
293298
},
294299
status,
295300
error: null,
296-
branch: compact(branch),
301+
branch: ssr === false ? [] : compact(branch),
297302
action_result,
298303
fetched
299304
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { redirect } from '@sveltejs/kit';
2+
3+
export const prerender = true;
4+
5+
export const ssr = false;
6+
7+
/** @type {import('@sveltejs/kit').Load} */
8+
export function load() {
9+
redirect(301, 'https://example.com/redirected');
10+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// spa shell should still prererender when +page.server.js exists but it has no load function
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>this won't be prerendered</h1>

packages/kit/test/prerendering/basics/test/tests.spec.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ test('renders a relative redirect', () => {
6060
);
6161
});
6262

63+
test('renders a shell when SSR is turned off and there is no server data', () => {
64+
const content = read('spa-shell.html');
65+
assert.match(
66+
content,
67+
/<!doctype html>\n<html lang="en">([\s]*?)<head>([\s]*?)<meta charset="utf-8" \/>([\s]*?)<meta name="viewport" content="width=device-width, initial-scale=1" \/>([\s\S]*?)<\/head>\n([\s]*?)<body>([\s]*?)<script>([\s\S]*?)<\/script>([\s]*?)<\/body>\n<\/html>/g
68+
);
69+
});
70+
6371
test('inserts http-equiv tag for cache-control headers', () => {
6472
const content = read('max-age.html');
6573
expect(content).toMatch('<meta http-equiv="cache-control" content="max-age=300">');

0 commit comments

Comments
 (0)