From 541c1ceace737b5d951f2f7477e7446179b4a2a5 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 18:27:51 +0100 Subject: [PATCH 1/6] [breaking] prerender shells when ssr false and prerender not false Closes #3966 --- .changeset/witty-falcons-begin.md | 5 ++++ packages/kit/src/core/prerender/prerender.js | 9 ++++++- packages/kit/src/runtime/server/page/index.js | 27 ++++++++++++++++++- .../test/prerendering/ssr-false/.gitignore | 1 + .../test/prerendering/ssr-false/package.json | 21 +++++++++++++++ .../test/prerendering/ssr-false/src/app.d.ts | 1 + .../test/prerendering/ssr-false/src/app.html | 11 ++++++++ .../ssr-false/src/routes/+layout.js | 1 + .../not-prerenderable-2/+page.server.js | 1 + .../routes/not-prerenderable-2/+page.svelte | 1 + .../ssr-false/src/routes/opt-out/+page.js | 1 + .../ssr-false/src/routes/opt-out/+page.svelte | 1 + .../routes/prerenderable-2/+page.server.js | 3 +++ .../src/routes/prerenderable-2/+page.svelte | 1 + .../src/routes/prerenderable/+page.js | 5 ++++ .../src/routes/prerenderable/+page.svelte | 1 + .../prerendering/ssr-false/svelte.config.js | 6 +++++ .../test/prerendering/ssr-false/test/test.js | 25 +++++++++++++++++ .../test/prerendering/ssr-false/tsconfig.json | 16 +++++++++++ .../prerendering/ssr-false/vite.config.js | 27 +++++++++++++++++++ pnpm-lock.yaml | 16 +++++++++++ 21 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 .changeset/witty-falcons-begin.md create mode 100644 packages/kit/test/prerendering/ssr-false/.gitignore create mode 100644 packages/kit/test/prerendering/ssr-false/package.json create mode 100644 packages/kit/test/prerendering/ssr-false/src/app.d.ts create mode 100644 packages/kit/test/prerendering/ssr-false/src/app.html create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/+layout.js create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.js create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.svelte create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.server.js create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.svelte create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js create mode 100644 packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.svelte create mode 100644 packages/kit/test/prerendering/ssr-false/svelte.config.js create mode 100644 packages/kit/test/prerendering/ssr-false/test/test.js create mode 100644 packages/kit/test/prerendering/ssr-false/tsconfig.json create mode 100644 packages/kit/test/prerendering/ssr-false/vite.config.js diff --git a/.changeset/witty-falcons-begin.md b/.changeset/witty-falcons-begin.md new file mode 100644 index 000000000000..008233babb17 --- /dev/null +++ b/.changeset/witty-falcons-begin.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +[breaking] prerender shells when ssr false and prerender not false diff --git a/packages/kit/src/core/prerender/prerender.js b/packages/kit/src/core/prerender/prerender.js index 7f1a9637240b..153a6884a620 100644 --- a/packages/kit/src/core/prerender/prerender.js +++ b/packages/kit/src/core/prerender/prerender.js @@ -401,7 +401,14 @@ export async function prerender() { validate_common_exports(page.shared, route.id); } - const prerender = get_option(nodes, 'prerender') ?? false; + const should_prerender = get_option(nodes, 'prerender'); + const prerender = + // Try prerendering if ssr is false and no server needed. + // People can opt out of this behavior by explicitly setting prerender to false + (should_prerender !== false && + get_option(nodes, 'ssr') === false && + !page?.server?.actions) || + (should_prerender ?? false); prerender_map.set(route.id, prerender); } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 4c3cb438612c..15d30a3cbcaa 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -79,13 +79,38 @@ 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'); + + console.log('SHOULD', should_prerender, event.url.href); 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. + // 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 diff --git a/packages/kit/test/prerendering/ssr-false/.gitignore b/packages/kit/test/prerendering/ssr-false/.gitignore new file mode 100644 index 000000000000..1e18f275e97c --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/.gitignore @@ -0,0 +1 @@ +!.env \ No newline at end of file diff --git a/packages/kit/test/prerendering/ssr-false/package.json b/packages/kit/test/prerendering/ssr-false/package.json new file mode 100644 index 000000000000..b51c6213dca0 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/package.json @@ -0,0 +1,21 @@ +{ + "name": "prerendering-test-basics", + "private": true, + "version": "0.0.2-next.0", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-kit sync && tsc && svelte-check", + "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" +} diff --git a/packages/kit/test/prerendering/ssr-false/src/app.d.ts b/packages/kit/test/prerendering/ssr-false/src/app.d.ts new file mode 100644 index 000000000000..7b39ff31cd34 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/app.d.ts @@ -0,0 +1 @@ +/// ; diff --git a/packages/kit/test/prerendering/ssr-false/src/app.html b/packages/kit/test/prerendering/ssr-false/src/app.html new file mode 100644 index 000000000000..d35c108bb8f2 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + + %sveltekit.body% + + diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/+layout.js b/packages/kit/test/prerendering/ssr-false/src/routes/+layout.js new file mode 100644 index 000000000000..a3d15781a772 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/+layout.js @@ -0,0 +1 @@ +export const ssr = false; diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js new file mode 100644 index 000000000000..576d6d28bc37 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js @@ -0,0 +1 @@ +export const actions = {}; diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte new file mode 100644 index 000000000000..3a4fb4b1663c --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte @@ -0,0 +1 @@ +

Not prerenderable because it has +page.server.js actions

diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.js b/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.js new file mode 100644 index 000000000000..d43d0cd2a55d --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.js @@ -0,0 +1 @@ +export const prerender = false; diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.svelte b/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.svelte new file mode 100644 index 000000000000..c2e1feb1d2eb --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/opt-out/+page.svelte @@ -0,0 +1 @@ +

prerenderable shell, but opted out of prerendering explicitly

diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.server.js b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.server.js new file mode 100644 index 000000000000..59b30f2adadf --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.server.js @@ -0,0 +1,3 @@ +export function load() { + throw new Error('I should not be called during prerendering'); +} diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.svelte b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.svelte new file mode 100644 index 000000000000..f844d12b1532 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable-2/+page.svelte @@ -0,0 +1 @@ +

prerenderable shell

diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js new file mode 100644 index 000000000000..d8e9c39c3871 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js @@ -0,0 +1,5 @@ +export function load() { + return { + dynamic: Math.random() + }; +} diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.svelte b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.svelte new file mode 100644 index 000000000000..f844d12b1532 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.svelte @@ -0,0 +1 @@ +

prerenderable shell

diff --git a/packages/kit/test/prerendering/ssr-false/svelte.config.js b/packages/kit/test/prerendering/ssr-false/svelte.config.js new file mode 100644 index 000000000000..821c14379ec8 --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/svelte.config.js @@ -0,0 +1,6 @@ +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: {} +}; + +export default config; diff --git a/packages/kit/test/prerendering/ssr-false/test/test.js b/packages/kit/test/prerendering/ssr-false/test/test.js new file mode 100644 index 000000000000..939d509b7f5f --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/test/test.js @@ -0,0 +1,25 @@ +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.run(); diff --git a/packages/kit/test/prerendering/ssr-false/tsconfig.json b/packages/kit/test/prerendering/ssr-false/tsconfig.json new file mode 100644 index 000000000000..df547741d5bb --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/tsconfig.json @@ -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" +} diff --git a/packages/kit/test/prerendering/ssr-false/vite.config.js b/packages/kit/test/prerendering/ssr-false/vite.config.js new file mode 100644 index 000000000000..fabe48d1677a --- /dev/null +++ b/packages/kit/test/prerendering/ssr-false/vite.config.js @@ -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; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 684b29de747c..b9de9e34f420 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -624,6 +624,22 @@ importers: uvu: 0.5.6 vite: 4.0.0 + packages/kit/test/prerendering/ssr-false: + specifiers: + '@sveltejs/kit': workspace:* + svelte: ^3.54.0 + svelte-check: ^2.9.2 + typescript: ^4.9.3 + uvu: ^0.5.6 + vite: ^4.0.0 + devDependencies: + '@sveltejs/kit': link:../../.. + svelte: 3.54.0 + svelte-check: 2.9.2_svelte@3.54.0 + typescript: 4.9.3 + uvu: 0.5.6 + vite: 4.0.0 + packages/migrate: specifiers: '@types/prompts': ^2.4.1 From 2282559233c4c31a237aabf9447d628866c2ac13 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 18:30:44 +0100 Subject: [PATCH 2/6] fix --- packages/kit/src/runtime/server/page/index.js | 1 - packages/kit/test/prerendering/ssr-false/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 15d30a3cbcaa..073951af680b 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -81,7 +81,6 @@ export async function render_page(event, route, page, options, state, resolve_op // causing functions to be omitted from the manifesst generated later const should_prerender = get_option(nodes, 'prerender'); - console.log('SHOULD', should_prerender, event.url.href); if (should_prerender) { const mod = leaf_node.server; if (mod && mod.actions) { diff --git a/packages/kit/test/prerendering/ssr-false/package.json b/packages/kit/test/prerendering/ssr-false/package.json index b51c6213dca0..5e73df540d25 100644 --- a/packages/kit/test/prerendering/ssr-false/package.json +++ b/packages/kit/test/prerendering/ssr-false/package.json @@ -1,5 +1,5 @@ { - "name": "prerendering-test-basics", + "name": "prerendering-test-ssr-false", "private": true, "version": "0.0.2-next.0", "scripts": { From 35c388fe24f87f2c7213a8ccae81af39e1771a5e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 21:31:55 +0100 Subject: [PATCH 3/6] keep implicitly rendered route in the manifest --- packages/kit/src/core/prerender/prerender.js | 11 ++++++----- packages/kit/src/runtime/server/page/index.js | 4 ++-- packages/kit/test/prerendering/ssr-false/test/test.js | 9 +++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/kit/src/core/prerender/prerender.js b/packages/kit/src/core/prerender/prerender.js index 153a6884a620..b10b1ca9bd4a 100644 --- a/packages/kit/src/core/prerender/prerender.js +++ b/packages/kit/src/core/prerender/prerender.js @@ -403,12 +403,13 @@ export async function prerender() { const should_prerender = get_option(nodes, 'prerender'); const prerender = - // Try prerendering if ssr is false and no server needed. + 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) || - (should_prerender ?? false); + (should_prerender !== false && get_option(nodes, 'ssr') === false && !page?.server?.actions + ? 'auto' + : false); prerender_map.set(route.id, prerender); } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 073951af680b..84c712d4fd68 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -87,8 +87,8 @@ export async function render_page(event, route, page, options, state, resolve_op throw new Error('Cannot prerender pages with actions'); } } else if (state.prerendering) { - // Try to render the shell when ssr is false. - // People can opt out of this behavior by explicitly setting prerender to false + // 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 && diff --git a/packages/kit/test/prerendering/ssr-false/test/test.js b/packages/kit/test/prerendering/ssr-false/test/test.js index 939d509b7f5f..6b70952efcce 100644 --- a/packages/kit/test/prerendering/ssr-false/test/test.js +++ b/packages/kit/test/prerendering/ssr-false/test/test.js @@ -22,4 +22,13 @@ 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(); From eb04979c767734f1489fce840f165ac11ebe05a3 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 21:37:13 +0100 Subject: [PATCH 4/6] there's no 1 --- .../{not-prerenderable-2 => not-prerenderable}/+page.server.js | 0 .../{not-prerenderable-2 => not-prerenderable}/+page.svelte | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/kit/test/prerendering/ssr-false/src/routes/{not-prerenderable-2 => not-prerenderable}/+page.server.js (100%) rename packages/kit/test/prerendering/ssr-false/src/routes/{not-prerenderable-2 => not-prerenderable}/+page.svelte (100%) diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable/+page.server.js similarity index 100% rename from packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.server.js rename to packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable/+page.server.js diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte b/packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable/+page.svelte similarity index 100% rename from packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable-2/+page.svelte rename to packages/kit/test/prerendering/ssr-false/src/routes/not-prerenderable/+page.svelte From e8f0832c206b1f4951a289117711103324745cb5 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 21:38:12 +0100 Subject: [PATCH 5/6] additional check --- .../prerendering/ssr-false/src/routes/prerenderable/+page.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js index d8e9c39c3871..59b30f2adadf 100644 --- a/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js +++ b/packages/kit/test/prerendering/ssr-false/src/routes/prerenderable/+page.js @@ -1,5 +1,3 @@ export function load() { - return { - dynamic: Math.random() - }; + throw new Error('I should not be called during prerendering'); } From 513fd1ee67327b918c939d8db4ac4a8a83d02635 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 13 Dec 2022 21:48:38 +0100 Subject: [PATCH 6/6] omit type check for now, uncovered a unreleated issue --- packages/kit/test/prerendering/ssr-false/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/test/prerendering/ssr-false/package.json b/packages/kit/test/prerendering/ssr-false/package.json index 5e73df540d25..0e42986cab3e 100644 --- a/packages/kit/test/prerendering/ssr-false/package.json +++ b/packages/kit/test/prerendering/ssr-false/package.json @@ -6,7 +6,6 @@ "dev": "vite dev", "build": "vite build", "preview": "vite preview", - "check": "svelte-kit sync && tsc && svelte-check", "test": "svelte-kit sync && pnpm build && uvu test" }, "devDependencies": {