Skip to content

Commit

Permalink
[breaking] prerender shells when ssr false and prerender not false (#…
Browse files Browse the repository at this point in the history
…8131)

* [breaking] prerender shells when ssr false and prerender not false

Closes #3966

* fix

* keep implicitly rendered route in the manifest

* there's no 1

* additional check

* omit type check for now, uncovered a unreleated issue
  • Loading branch information
dummdidumm authored Dec 13, 2022
1 parent 8f807ea commit f1ec316
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-falcons-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[breaking] prerender shells when ssr false and prerender not false
10 changes: 9 additions & 1 deletion packages/kit/src/core/prerender/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,15 @@ export async function prerender() {
validate_common_exports(page.universal, route.id);
}

const prerender = get_option(nodes, 'prerender') ?? false;
const should_prerender = get_option(nodes, 'prerender');
const prerender =
should_prerender === true ||
// Try prerendering if ssr is false and no server needed. Set it to 'auto' so that
// the route is not removed from the manifest, there could be a server load function.
// People can opt out of this behavior by explicitly setting prerender to false
(should_prerender !== false && get_option(nodes, 'ssr') === false && !page?.server?.actions
? 'auto'
: false);

prerender_map.set(route.id, prerender);
}
Expand Down
26 changes: 25 additions & 1 deletion packages/kit/src/runtime/server/page/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,37 @@ export async function render_page(event, route, page, options, state, resolve_op
// it's crucial that we do this before returning the non-SSR response, otherwise
// SvelteKit will erroneously believe that the path has been prerendered,
// causing functions to be omitted from the manifesst generated later
const should_prerender = get_option(nodes, 'prerender') ?? false;
const should_prerender = get_option(nodes, 'prerender');

if (should_prerender) {
const mod = leaf_node.server;
if (mod && mod.actions) {
throw new Error('Cannot prerender pages with actions');
}
} else if (state.prerendering) {
// Try to render the shell when ssr is false and prerendering not explicitly disabled.
// People can opt out of this behavior by explicitly setting prerender to false.
if (
should_prerender !== false &&
get_option(nodes, 'ssr') === false &&
!leaf_node.server?.actions
) {
return await render_response({
branch: [],
fetched: [],
page_config: {
ssr: false,
csr: get_option(nodes, 'csr') ?? true
},
status,
error: null,
event,
options,
state,
resolve_opts
});
}

// if the page isn't marked as prerenderable, then bail out at this point
return new Response(undefined, {
status: 204
Expand Down
1 change: 1 addition & 0 deletions packages/kit/test/prerendering/ssr-false/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!.env
20 changes: 20 additions & 0 deletions packages/kit/test/prerendering/ssr-false/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "prerendering-test-ssr-false",
"private": true,
"version": "0.0.2-next.0",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"test": "svelte-kit sync && pnpm build && uvu test"
},
"devDependencies": {
"@sveltejs/kit": "workspace:*",
"svelte": "^3.54.0",
"svelte-check": "^2.9.2",
"typescript": "^4.9.3",
"uvu": "^0.5.6",
"vite": "^4.0.0"
},
"type": "module"
}
1 change: 1 addition & 0 deletions packages/kit/test/prerendering/ssr-false/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="@sveltejs/kit" />;
11 changes: 11 additions & 0 deletions packages/kit/test/prerendering/ssr-false/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body>
%sveltekit.body%
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const ssr = false;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const actions = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Not prerenderable because it has +page.server.js actions</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const prerender = false;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>prerenderable shell, but opted out of prerendering explicitly</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function load() {
throw new Error('I should not be called during prerendering');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>prerenderable shell</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function load() {
throw new Error('I should not be called during prerendering');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>prerenderable shell</p>
6 changes: 6 additions & 0 deletions packages/kit/test/prerendering/ssr-false/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {}
};

export default config;
34 changes: 34 additions & 0 deletions packages/kit/test/prerendering/ssr-false/test/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as fs from 'fs';
import { fileURLToPath } from 'url';
import { test } from 'uvu';
import * as assert from 'uvu/assert';

const build = fileURLToPath(new URL('../.svelte-kit/output/prerendered/pages', import.meta.url));

/** @param {string} file */
const read = (file, encoding = 'utf-8') => fs.readFileSync(`${build}/${file}`, encoding);

test('prerenders /prerenderable shell', () => {
const content = read('prerenderable.html');
assert.ok(!content.includes('prerenderable shell'));
});

test('prerenders /prerenderable-2 shell', () => {
const content = read('prerenderable-2.html');
assert.ok(!content.includes('prerenderable shell'));
});

test('does not prerender non prerenderable things', () => {
assert.equal(fs.readdirSync(build).length, 2);
});

test('keeps not-explicitly-prerendered routes in the manifest', () => {
const manifest = fileURLToPath(
new URL('../.svelte-kit/output/server/manifest.js', import.meta.url)
);
const content = fs.readFileSync(manifest, 'utf-8');
assert.ok(content.includes('/prerenderable'));
assert.ok(content.includes('/prerenderable-2'));
});

test.run();
16 changes: 16 additions & 0 deletions packages/kit/test/prerendering/ssr-false/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"noEmit": true,
"module": "esnext",
"moduleResolution": "node",
"paths": {
"@sveltejs/kit": ["../../../types"],
"$lib": ["./src/lib"],
"$lib/*": ["./src/lib/*"],
"types": ["../../../types/internal"]
}
},
"extends": "./.svelte-kit/tsconfig.json"
}
27 changes: 27 additions & 0 deletions packages/kit/test/prerendering/ssr-false/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as path from 'path';
import { sveltekit } from '@sveltejs/kit/vite';

/** @type {import('vite').UserConfig} */
const config = {
build: {
minify: false
},

clearScreen: false,

logLevel: 'silent',

plugins: [sveltekit()],

define: {
'process.env.MY_ENV': '"MY_ENV DEFINED"'
},

server: {
fs: {
allow: [path.resolve('../../../src')]
}
}
};

export default config;
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f1ec316

Please sign in to comment.