From 0579f45e5822d818fa45073da210a957a7a20212 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 14:42:07 +0200 Subject: [PATCH 01/16] [breaking] add error.html This is a static error page that will be rendered by the server when everything else goes wrong Closes #3068 --- .changeset/quiet-camels-shop.md | 6 ++++ documentation/docs/01-project-structure.md | 2 ++ documentation/docs/03-routing.md | 2 +- documentation/docs/15-configuration.md | 3 +- .../templates/default/src/error.html | 11 ++++++++ .../templates/libskeleton/src/error.html | 11 ++++++++ .../templates/skeleton/src/error.html | 11 ++++++++ packages/kit/src/core/config/index.js | 28 +++++++++++++++++++ packages/kit/src/core/config/options.js | 3 +- .../src/exports/vite/build/build_server.js | 9 ++++-- packages/kit/src/exports/vite/dev/index.js | 3 +- packages/kit/src/runtime/server/index.js | 4 +-- packages/kit/src/runtime/server/page/index.js | 9 ++---- .../runtime/server/page/respond_with_error.js | 2 +- packages/kit/types/index.d.ts | 1 + packages/kit/types/internal.d.ts | 1 + 16 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 .changeset/quiet-camels-shop.md create mode 100644 packages/create-svelte/templates/default/src/error.html create mode 100644 packages/create-svelte/templates/libskeleton/src/error.html create mode 100644 packages/create-svelte/templates/skeleton/src/error.html diff --git a/.changeset/quiet-camels-shop.md b/.changeset/quiet-camels-shop.md new file mode 100644 index 000000000000..05eab4f19189 --- /dev/null +++ b/.changeset/quiet-camels-shop.md @@ -0,0 +1,6 @@ +--- +'@sveltejs/kit': patch +'create-svelte': patch +--- + +[breaking] add error.html page diff --git a/documentation/docs/01-project-structure.md b/documentation/docs/01-project-structure.md index 737c5b9f8da1..074cf1d61a7f 100644 --- a/documentation/docs/01-project-structure.md +++ b/documentation/docs/01-project-structure.md @@ -14,6 +14,7 @@ my-project/ │ ├ routes/ │ │ └ [your routes] │ ├ app.html +│ ├ error.html │ └ hooks.js ├ static/ │ └ [your static assets] @@ -41,6 +42,7 @@ The `src` directory contains the meat of your project. - `%sveltekit.body%` — the markup for a rendered page. Typically this lives inside a `
` or other element, rather than directly inside ``, to prevent bugs caused by browser extensions injecting elements that are then destroyed by the hydration process - `%sveltekit.assets%` — either [`paths.assets`](/docs/configuration#paths), if specified, or a relative path to [`paths.base`](/docs/configuration#base) - `%sveltekit.nonce%` — a [CSP](/docs/configuration#csp) nonce for manually included links and scripts, if used +- `error.html` is the page that is rendered when everything else fails - `hooks.js` (optional) contains your application's [hooks](/docs/hooks) - `service-worker.js` (optional) contains your [service worker](/docs/service-workers) diff --git a/documentation/docs/03-routing.md b/documentation/docs/03-routing.md index b085b4f9ac0f..7f03a125ee88 100644 --- a/documentation/docs/03-routing.md +++ b/documentation/docs/03-routing.md @@ -190,7 +190,7 @@ If an error occurs during `load`, SvelteKit will render a default error page. Yo

{$page.status}: {$page.error.message}

``` -SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and `src/routes/+error.svelte` before rendering the default error page. +SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and `src/routes/+error.svelte` before rendering the default error page. If that fails, the contents of a static error page (`src/error.html` by default) will be rendered instead. ### +layout diff --git a/documentation/docs/15-configuration.md b/documentation/docs/15-configuration.md index 6b39c660ea14..8294a8dc9805 100644 --- a/documentation/docs/15-configuration.md +++ b/documentation/docs/15-configuration.md @@ -40,7 +40,8 @@ const config = { params: 'src/params', routes: 'src/routes', serviceWorker: 'src/service-worker', - template: 'src/app.html' + template: 'src/app.html', + errorPage: 'src/error.html' }, inlineStyleThreshold: 0, methodOverride: { diff --git a/packages/create-svelte/templates/default/src/error.html b/packages/create-svelte/templates/default/src/error.html new file mode 100644 index 000000000000..1d92e33297fc --- /dev/null +++ b/packages/create-svelte/templates/default/src/error.html @@ -0,0 +1,11 @@ + + + + + Error + + +

Error

+

An error occurred.

+ + diff --git a/packages/create-svelte/templates/libskeleton/src/error.html b/packages/create-svelte/templates/libskeleton/src/error.html new file mode 100644 index 000000000000..1d92e33297fc --- /dev/null +++ b/packages/create-svelte/templates/libskeleton/src/error.html @@ -0,0 +1,11 @@ + + + + + Error + + +

Error

+

An error occurred.

+ + diff --git a/packages/create-svelte/templates/skeleton/src/error.html b/packages/create-svelte/templates/skeleton/src/error.html new file mode 100644 index 000000000000..1d92e33297fc --- /dev/null +++ b/packages/create-svelte/templates/skeleton/src/error.html @@ -0,0 +1,11 @@ + + + + + Error + + +

Error

+

An error occurred.

+ + diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index f903bb086b05..7b16410684ef 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -37,6 +37,34 @@ export function load_template(cwd, config) { return fs.readFileSync(template, 'utf-8'); } +/** + * Loads the error page (src/error.html by default) if it exists. + * Falls back to a generic error page content. + * @param {string} cwd + * @param {import('types').ValidatedConfig} config + */ +export function load_error_page(cwd, config) { + const { errorPage } = config.kit.files; + const relative = path.relative(cwd, errorPage); + + if (fs.existsSync(errorPage)) { + return fs.readFileSync(errorPage, 'utf-8'); + } else { + console.log(`${relative} does not exist. Using generic error page instead.`); + return ` + + + + Error + + +

Error

+

An error occurred.

+ +`; + } +} + /** * Loads and validates svelte.config.js * @param {{ cwd?: string }} options diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index d460596a10e8..a18287bb4047 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -140,7 +140,8 @@ const options = object( params: string(join('src', 'params')), routes: string(join('src', 'routes')), serviceWorker: string(join('src', 'service-worker')), - template: string(join('src', 'app.html')) + template: string(join('src', 'app.html')), + errorPage: string(join('src', 'error.html')) }), // TODO: remove this for the 1.0 release diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js index 4b9782a7b963..860d4ae3c61c 100644 --- a/packages/kit/src/exports/vite/build/build_server.js +++ b/packages/kit/src/exports/vite/build/build_server.js @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import { mkdirp, posixify } from '../../../utils/filesystem.js'; import { get_vite_config, merge_vite_configs, resolve_entry } from '../utils.js'; -import { load_template } from '../../../core/config/index.js'; +import { load_error_page, load_template } from '../../../core/config/index.js'; import { runtime_directory } from '../../../core/utils.js'; import { create_build, find_deps, get_default_build_config, is_http_method } from './utils.js'; import { s } from '../../../utils/misc.js'; @@ -14,9 +14,10 @@ import { s } from '../../../utils/misc.js'; * has_service_worker: boolean; * runtime: string; * template: string; + * error_page: string; * }} opts */ -const server_template = ({ config, hooks, has_service_worker, runtime, template }) => ` +const server_template = ({ config, hooks, has_service_worker, runtime, template, error_page }) => ` import root from '__GENERATED__/root.svelte'; import { respond } from '${runtime}/server/index.js'; import { set_paths, assets, base } from '${runtime}/paths.js'; @@ -80,6 +81,7 @@ export class Server { router: ${s(config.kit.browser.router)}, template, template_contains_nonce: ${template.includes('%sveltekit.nonce%')}, + error_page: '${error_page}', trailing_slash: ${s(config.kit.trailingSlash)} }; } @@ -205,7 +207,8 @@ export async function build_server(options, client) { hooks: app_relative(hooks_file), has_service_worker: config.kit.serviceWorker.register && !!service_worker_entry_file, runtime: posixify(path.relative(build_dir, runtime_directory)), - template: load_template(cwd, config) + template: load_template(cwd, config), + error_page: load_error_page(cwd, config) }) ); diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index 77cb0bfb9e86..cacc01c5bdff 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -7,7 +7,7 @@ import { getRequest, setResponse } from '../../../exports/node/index.js'; import { installPolyfills } from '../../../exports/node/polyfills.js'; import { coalesce_to_error } from '../../../utils/error.js'; import { posixify } from '../../../utils/filesystem.js'; -import { load_template } from '../../../core/config/index.js'; +import { load_error_page, load_template } from '../../../core/config/index.js'; import { SVELTE_KIT_ASSETS } from '../../../core/constants.js'; import * as sync from '../../../core/sync/sync.js'; import { get_mime_lookup, runtime_base, runtime_prefix } from '../../../core/utils.js'; @@ -427,6 +427,7 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { ); }, template_contains_nonce: template.includes('%sveltekit.nonce%'), + error_page: load_error_page(cwd, svelte_config), trailing_slash: svelte_config.kit.trailingSlash }, { diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js index 804823673a6c..c82b985b4602 100644 --- a/packages/kit/src/runtime/server/index.js +++ b/packages/kit/src/runtime/server/index.js @@ -482,9 +482,7 @@ export async function respond(request, options, state) { resolve_opts }); } catch (/** @type {unknown} */ e) { - const error = coalesce_to_error(e); - - return new Response(options.dev ? error.stack : error.message, { + return new Response(options.error_page, { status: 500 }); } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 39f5cbdf74fd..358201ef18bf 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -278,13 +278,8 @@ export async function render_page(event, route, page, options, state, resolve_op } // if we're still here, it means the error happened in the root layout, - // which means we have to fall back to a plain text response - // TODO since the requester is expecting HTML, maybe it makes sense to - // doll this up a bit - return new Response( - error instanceof HttpError ? error.message : options.get_stack(error), - { status } - ); + // which means we have to fall back to error.html + return new Response(options.error_page, { status }); } } else { // push an empty slot so we can rewind past gaps to the diff --git a/packages/kit/src/runtime/server/page/respond_with_error.js b/packages/kit/src/runtime/server/page/respond_with_error.js index 001fdd5a8cea..665e99a55012 100644 --- a/packages/kit/src/runtime/server/page/respond_with_error.js +++ b/packages/kit/src/runtime/server/page/respond_with_error.js @@ -88,7 +88,7 @@ export async function respond_with_error({ event, options, state, status, error, options.handle_error(error, event); - return new Response(error.stack, { + return new Response(options.error_page, { status: 500 }); } diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index f5033d642bea..76086c75c2f6 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -143,6 +143,7 @@ export interface KitConfig { routes?: string; serviceWorker?: string; template?: string; + errorPage?: string; }; inlineStyleThreshold?: number; methodOverride?: { diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts index 2543bc14c35f..d8ae3e6606b9 100644 --- a/packages/kit/types/internal.d.ts +++ b/packages/kit/types/internal.d.ts @@ -321,6 +321,7 @@ export interface SSROptions { nonce: string; }): string; template_contains_nonce: boolean; + error_page: string; trailing_slash: TrailingSlash; } From 3bc41bd5187d755f9066639d627739eef37318cf Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 15:25:11 +0200 Subject: [PATCH 02/16] await native navigations to prevent content flashes --- packages/kit/src/runtime/client/client.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 4bf1994d710a..09bd967bdf5b 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -731,7 +731,7 @@ export function create_client({ target, base, trailing_slash }) { } } catch (e) { // something went catastrophically wrong — bail and defer to the server - native_navigation(url); + await native_navigation(url); return; } @@ -841,7 +841,7 @@ export function create_client({ target, base, trailing_slash }) { // if we get here, it's because the root `load` function failed, // and we need to fall back to the server - native_navigation(url); + await native_navigation(url); return; } } else { @@ -896,7 +896,7 @@ export function create_client({ target, base, trailing_slash }) { if (!res.ok || server_data_nodes?.type !== 'data') { // at this point we have no choice but to fall back to the server - native_navigation(url); + await native_navigation(url); // @ts-expect-error return; From 9d254a3c4e13acb66e6351a0897192fcb408f5fb Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 15:26:17 +0200 Subject: [PATCH 03/16] thank you test for uncovering my inability to set the response's content-type --- packages/kit/src/runtime/server/index.js | 1 + packages/kit/src/runtime/server/page/index.js | 5 ++++- .../src/runtime/server/page/respond_with_error.js | 1 + packages/kit/test/apps/basics/src/error.html | 10 ++++++++++ .../test/apps/basics/src/routes/+layout.server.js | 12 ++++++++++++ .../basics/src/routes/errors/error-html/+page.svelte | 8 ++++++++ .../errors/error-html/make-root-fail/+server.js | 6 ++++++ packages/kit/test/apps/basics/test/client.test.js | 6 ++++++ 8 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/kit/test/apps/basics/src/error.html create mode 100644 packages/kit/test/apps/basics/src/routes/errors/error-html/+page.svelte create mode 100644 packages/kit/test/apps/basics/src/routes/errors/error-html/make-root-fail/+server.js diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js index c82b985b4602..e644b4070b61 100644 --- a/packages/kit/src/runtime/server/index.js +++ b/packages/kit/src/runtime/server/index.js @@ -483,6 +483,7 @@ export async function respond(request, options, state) { }); } catch (/** @type {unknown} */ e) { return new Response(options.error_page, { + headers: { 'content-type': 'text/html; charset=utf-8' }, status: 500 }); } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 358201ef18bf..ddb24b1619d9 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -279,7 +279,10 @@ export async function render_page(event, route, page, options, state, resolve_op // if we're still here, it means the error happened in the root layout, // which means we have to fall back to error.html - return new Response(options.error_page, { status }); + return new Response(options.error_page, { + status, + headers: { 'content-type': 'text/html; charset=utf-8' } + }); } } else { // push an empty slot so we can rewind past gaps to the diff --git a/packages/kit/src/runtime/server/page/respond_with_error.js b/packages/kit/src/runtime/server/page/respond_with_error.js index 665e99a55012..4263047f4aa1 100644 --- a/packages/kit/src/runtime/server/page/respond_with_error.js +++ b/packages/kit/src/runtime/server/page/respond_with_error.js @@ -89,6 +89,7 @@ export async function respond_with_error({ event, options, state, status, error, options.handle_error(error, event); return new Response(options.error_page, { + headers: { 'content-type': 'text/html; charset=utf-8' }, status: 500 }); } diff --git a/packages/kit/test/apps/basics/src/error.html b/packages/kit/test/apps/basics/src/error.html new file mode 100644 index 000000000000..4a070cb81fb1 --- /dev/null +++ b/packages/kit/test/apps/basics/src/error.html @@ -0,0 +1,10 @@ + + + + + Error + + +

This is the static error page

+ + diff --git a/packages/kit/test/apps/basics/src/routes/+layout.server.js b/packages/kit/test/apps/basics/src/routes/+layout.server.js index bacb24019ecc..cb10abf04b64 100644 --- a/packages/kit/test/apps/basics/src/routes/+layout.server.js +++ b/packages/kit/test/apps/basics/src/routes/+layout.server.js @@ -1,4 +1,16 @@ +let should_fail = false; +/** + * @param {boolean} value + */ +export function set_should_fail(value) { + should_fail = value; +} + export async function load() { + if (should_fail) { + set_should_fail(false); + throw new Error('Failed to load'); + } // Do NOT make this load function depend on something which would cause it to rerun return { rootlayout: 'rootlayout' diff --git a/packages/kit/test/apps/basics/src/routes/errors/error-html/+page.svelte b/packages/kit/test/apps/basics/src/routes/errors/error-html/+page.svelte new file mode 100644 index 000000000000..2fda2e2e0f14 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/error-html/+page.svelte @@ -0,0 +1,8 @@ + + + diff --git a/packages/kit/test/apps/basics/src/routes/errors/error-html/make-root-fail/+server.js b/packages/kit/test/apps/basics/src/routes/errors/error-html/make-root-fail/+server.js new file mode 100644 index 000000000000..7c3f14cfd285 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/errors/error-html/make-root-fail/+server.js @@ -0,0 +1,6 @@ +import { set_should_fail } from '../../../+layout.server'; + +export function GET() { + set_should_fail(true); + return new Response(); +} diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 03da4032df27..b2d8c224f660 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -305,6 +305,12 @@ test.describe('Errors', () => { ); expect(await page.innerHTML('h1')).toBe('401'); }); + + test('Root error falls back to error.html', async ({ page }) => { + await page.goto('/errors/error-html'); + await page.click('button'); + expect(await page.textContent('p')).toBe('This is the static error page'); + }); }); test.describe('Load', () => { From 3b6d4258b2c118a71559e651b228e24e925aa816 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 17:35:38 +0200 Subject: [PATCH 04/16] error page can retrieve status / message --- .../create-svelte/templates/default/src/error.html | 4 ++-- .../templates/libskeleton/src/error.html | 4 ++-- .../templates/skeleton/src/error.html | 4 ++-- packages/kit/src/core/config/index.js | 4 ++-- .../kit/src/exports/vite/build/build_server.js | 6 +++++- packages/kit/src/exports/vite/dev/index.js | 7 ++++++- packages/kit/src/runtime/server/index.js | 8 +++----- packages/kit/src/runtime/server/page/index.js | 9 +++++---- .../src/runtime/server/page/respond_with_error.js | 7 ++----- packages/kit/src/runtime/server/utils.js | 14 ++++++++++++++ packages/kit/test/apps/basics/src/error.html | 3 ++- packages/kit/test/apps/basics/test/client.test.js | 5 ++++- packages/kit/types/internal.d.ts | 2 +- 13 files changed, 50 insertions(+), 27 deletions(-) diff --git a/packages/create-svelte/templates/default/src/error.html b/packages/create-svelte/templates/default/src/error.html index 1d92e33297fc..8b63e78c7c53 100644 --- a/packages/create-svelte/templates/default/src/error.html +++ b/packages/create-svelte/templates/default/src/error.html @@ -5,7 +5,7 @@ Error -

Error

-

An error occurred.

+

Error - %sveltekit.status%

+

%sveltekit.message%

diff --git a/packages/create-svelte/templates/libskeleton/src/error.html b/packages/create-svelte/templates/libskeleton/src/error.html index 1d92e33297fc..8b63e78c7c53 100644 --- a/packages/create-svelte/templates/libskeleton/src/error.html +++ b/packages/create-svelte/templates/libskeleton/src/error.html @@ -5,7 +5,7 @@ Error -

Error

-

An error occurred.

+

Error - %sveltekit.status%

+

%sveltekit.message%

diff --git a/packages/create-svelte/templates/skeleton/src/error.html b/packages/create-svelte/templates/skeleton/src/error.html index 1d92e33297fc..8b63e78c7c53 100644 --- a/packages/create-svelte/templates/skeleton/src/error.html +++ b/packages/create-svelte/templates/skeleton/src/error.html @@ -5,7 +5,7 @@ Error -

Error

-

An error occurred.

+

Error - %sveltekit.status%

+

%sveltekit.message%

diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 7b16410684ef..766895f5ee77 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -58,8 +58,8 @@ export function load_error_page(cwd, config) { Error -

Error

-

An error occurred.

+

Error - %sveltekit.status%

+

%sveltekit.message%

`; } diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js index 860d4ae3c61c..c73a4fcd68cd 100644 --- a/packages/kit/src/exports/vite/build/build_server.js +++ b/packages/kit/src/exports/vite/build/build_server.js @@ -31,6 +31,10 @@ const template = ({ head, body, assets, nonce }) => ${s(template) .replace(/%sveltekit\.assets%/g, '" + assets + "') .replace(/%sveltekit\.nonce%/g, '" + nonce + "')}; +const error_page = ({ status, message }) => ${s(error_page) + .replace(/%sveltekit\.status%/g, '" + status + "') + .replace(/%sveltekit\.message%/g, '" + message + "')}; + let read = null; set_paths(${s(config.kit.paths)}); @@ -81,7 +85,7 @@ export class Server { router: ${s(config.kit.browser.router)}, template, template_contains_nonce: ${template.includes('%sveltekit.nonce%')}, - error_page: '${error_page}', + error_page, trailing_slash: ${s(config.kit.trailingSlash)} }; } diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index cacc01c5bdff..ca8d4d0381f8 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -371,6 +371,7 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { } const template = load_template(cwd, svelte_config); + const error_page = load_error_page(cwd, svelte_config); const rendered = await respond( request, @@ -427,7 +428,11 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { ); }, template_contains_nonce: template.includes('%sveltekit.nonce%'), - error_page: load_error_page(cwd, svelte_config), + error_page: ({ status, message }) => { + return error_page + .replace(/%sveltekit\.status%/g, String(status)) + .replace(/%sveltekit\.message%/g, message); + }, trailing_slash: svelte_config.kit.trailingSlash }, { diff --git a/packages/kit/src/runtime/server/index.js b/packages/kit/src/runtime/server/index.js index e644b4070b61..462ca19d861b 100644 --- a/packages/kit/src/runtime/server/index.js +++ b/packages/kit/src/runtime/server/index.js @@ -3,7 +3,7 @@ import { render_page } from './page/index.js'; import { render_response } from './page/render.js'; import { respond_with_error } from './page/respond_with_error.js'; import { coalesce_to_error, normalize_error } from '../../utils/error.js'; -import { serialize_error, GENERIC_ERROR, error_to_pojo } from './utils.js'; +import { serialize_error, GENERIC_ERROR, error_to_pojo, static_error_page } from './utils.js'; import { decode_params, disable_search, normalize_path } from '../../utils/url.js'; import { exec } from '../../utils/routing.js'; import { negotiate } from '../../utils/http.js'; @@ -482,10 +482,8 @@ export async function respond(request, options, state) { resolve_opts }); } catch (/** @type {unknown} */ e) { - return new Response(options.error_page, { - headers: { 'content-type': 'text/html; charset=utf-8' }, - status: 500 - }); + const error = coalesce_to_error(e); + return static_error_page(options, 500, error.message); } } } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index ddb24b1619d9..f09fad1baf21 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -1,7 +1,7 @@ import { negotiate } from '../../../utils/http.js'; import { render_response } from './render.js'; import { respond_with_error } from './respond_with_error.js'; -import { method_not_allowed, error_to_pojo, allowed_methods } from '../utils.js'; +import { method_not_allowed, error_to_pojo, allowed_methods, static_error_page } from '../utils.js'; import { create_fetch } from './fetch.js'; import { HttpError, Redirect } from '../../control.js'; import { error, json } from '../../../exports/index.js'; @@ -279,10 +279,11 @@ export async function render_page(event, route, page, options, state, resolve_op // if we're still here, it means the error happened in the root layout, // which means we have to fall back to error.html - return new Response(options.error_page, { + return static_error_page( + options, status, - headers: { 'content-type': 'text/html; charset=utf-8' } - }); + /** @type {HttpError | Error} */ (error).message + ); } } else { // push an empty slot so we can rewind past gaps to the diff --git a/packages/kit/src/runtime/server/page/respond_with_error.js b/packages/kit/src/runtime/server/page/respond_with_error.js index 4263047f4aa1..c4f7b4437b45 100644 --- a/packages/kit/src/runtime/server/page/respond_with_error.js +++ b/packages/kit/src/runtime/server/page/respond_with_error.js @@ -1,7 +1,7 @@ import { render_response } from './render.js'; import { load_data, load_server_data } from './load_data.js'; import { coalesce_to_error } from '../../../utils/error.js'; -import { GENERIC_ERROR } from '../utils.js'; +import { GENERIC_ERROR, static_error_page } from '../utils.js'; import { create_fetch } from './fetch.js'; /** @@ -88,9 +88,6 @@ export async function respond_with_error({ event, options, state, status, error, options.handle_error(error, event); - return new Response(options.error_page, { - headers: { 'content-type': 'text/html; charset=utf-8' }, - status: 500 - }); + return static_error_page(options, 500, error.message); } } diff --git a/packages/kit/src/runtime/server/utils.js b/packages/kit/src/runtime/server/utils.js index 6efd4f93e5b7..bb3be1281f2f 100644 --- a/packages/kit/src/runtime/server/utils.js +++ b/packages/kit/src/runtime/server/utils.js @@ -114,3 +114,17 @@ export function allowed_methods(mod) { return allowed; } + +/** + * Return as a response that renders the error.html + * + * @param {import('types').SSROptions} options + * @param {number} status + * @param {string} message + */ +export function static_error_page(options, status, message) { + return new Response(options.error_page({ status, message }), { + headers: { 'content-type': 'text/html; charset=utf-8' }, + status + }); +} diff --git a/packages/kit/test/apps/basics/src/error.html b/packages/kit/test/apps/basics/src/error.html index 4a070cb81fb1..14d6424789f9 100644 --- a/packages/kit/test/apps/basics/src/error.html +++ b/packages/kit/test/apps/basics/src/error.html @@ -5,6 +5,7 @@ Error -

This is the static error page

+

Error - %sveltekit.status%

+

This is the static error page with the following message: %sveltekit.message%

diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index b2d8c224f660..fd73413f6823 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -309,7 +309,10 @@ test.describe('Errors', () => { test('Root error falls back to error.html', async ({ page }) => { await page.goto('/errors/error-html'); await page.click('button'); - expect(await page.textContent('p')).toBe('This is the static error page'); + expect(await page.textContent('h1')).toBe('Error - 500'); + expect(await page.textContent('p')).toBe( + 'This is the static error page with the following message: Failed to load' + ); }); }); diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts index d8ae3e6606b9..312923d1fe42 100644 --- a/packages/kit/types/internal.d.ts +++ b/packages/kit/types/internal.d.ts @@ -321,7 +321,7 @@ export interface SSROptions { nonce: string; }): string; template_contains_nonce: boolean; - error_page: string; + error_page({ message, status }: { message: string; status: number }): string; trailing_slash: TrailingSlash; } From 3c8b5f8c850d556ddaec97383ad78256412be67e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 17:37:09 +0200 Subject: [PATCH 05/16] fix test --- packages/kit/src/core/config/index.spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js index aa748ec0a92a..c39ae72fd304 100644 --- a/packages/kit/src/core/config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -84,7 +84,8 @@ const get_defaults = (prefix = '') => ({ params: join(prefix, 'src/params'), routes: join(prefix, 'src/routes'), serviceWorker: join(prefix, 'src/service-worker'), - template: join(prefix, 'src/app.html') + template: join(prefix, 'src/app.html'), + errorPage: join(prefix, 'src/error.html') }, headers: undefined, host: undefined, From d81f4494cd1775888188b798756dacf5417108a2 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 18:01:35 +0200 Subject: [PATCH 06/16] shhh --- packages/kit/src/core/config/index.js | 5 +---- packages/kit/src/exports/vite/build/build_server.js | 2 +- packages/kit/src/exports/vite/dev/index.js | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 766895f5ee77..24377df3d8ef 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -40,17 +40,14 @@ export function load_template(cwd, config) { /** * Loads the error page (src/error.html by default) if it exists. * Falls back to a generic error page content. - * @param {string} cwd * @param {import('types').ValidatedConfig} config */ -export function load_error_page(cwd, config) { +export function load_error_page(config) { const { errorPage } = config.kit.files; - const relative = path.relative(cwd, errorPage); if (fs.existsSync(errorPage)) { return fs.readFileSync(errorPage, 'utf-8'); } else { - console.log(`${relative} does not exist. Using generic error page instead.`); return ` diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js index c73a4fcd68cd..dd3b00e42f97 100644 --- a/packages/kit/src/exports/vite/build/build_server.js +++ b/packages/kit/src/exports/vite/build/build_server.js @@ -212,7 +212,7 @@ export async function build_server(options, client) { has_service_worker: config.kit.serviceWorker.register && !!service_worker_entry_file, runtime: posixify(path.relative(build_dir, runtime_directory)), template: load_template(cwd, config), - error_page: load_error_page(cwd, config) + error_page: load_error_page(config) }) ); diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index ca8d4d0381f8..dcbafa230758 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -371,7 +371,7 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { } const template = load_template(cwd, svelte_config); - const error_page = load_error_page(cwd, svelte_config); + const error_page = load_error_page(svelte_config); const rendered = await respond( request, From d9b1dede3719e68075cab3896994ac1dfc123094 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 29 Aug 2022 18:05:53 +0200 Subject: [PATCH 07/16] note placeholders --- documentation/docs/01-project-structure.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/docs/01-project-structure.md b/documentation/docs/01-project-structure.md index 074cf1d61a7f..d4973bede651 100644 --- a/documentation/docs/01-project-structure.md +++ b/documentation/docs/01-project-structure.md @@ -42,7 +42,9 @@ The `src` directory contains the meat of your project. - `%sveltekit.body%` — the markup for a rendered page. Typically this lives inside a `
` or other element, rather than directly inside ``, to prevent bugs caused by browser extensions injecting elements that are then destroyed by the hydration process - `%sveltekit.assets%` — either [`paths.assets`](/docs/configuration#paths), if specified, or a relative path to [`paths.base`](/docs/configuration#base) - `%sveltekit.nonce%` — a [CSP](/docs/configuration#csp) nonce for manually included links and scripts, if used -- `error.html` is the page that is rendered when everything else fails +- `error.html` is the page that is rendered when everything else fails. It can contain the following placeholders: + - `%sveltekit.status%` — the HTTP status + - `%sveltekit.message%` — the error message - `hooks.js` (optional) contains your application's [hooks](/docs/hooks) - `service-worker.js` (optional) contains your [service worker](/docs/service-workers) From d5c986bf28e889dddbcef4ab3af8ca5a8083f508 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 29 Aug 2022 17:39:00 -0400 Subject: [PATCH 08/16] move default error template into separate file --- .../kit/src/core/config/default-error.html | 11 +++++++++ packages/kit/src/core/config/index.js | 23 ++++++------------- 2 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 packages/kit/src/core/config/default-error.html diff --git a/packages/kit/src/core/config/default-error.html b/packages/kit/src/core/config/default-error.html new file mode 100644 index 000000000000..8b63e78c7c53 --- /dev/null +++ b/packages/kit/src/core/config/default-error.html @@ -0,0 +1,11 @@ + + + + + Error + + +

Error - %sveltekit.status%

+

%sveltekit.message%

+ + diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 24377df3d8ef..92e7ca9926f5 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -44,22 +44,7 @@ export function load_template(cwd, config) { */ export function load_error_page(config) { const { errorPage } = config.kit.files; - - if (fs.existsSync(errorPage)) { - return fs.readFileSync(errorPage, 'utf-8'); - } else { - return ` - - - - Error - - -

Error - %sveltekit.status%

-

%sveltekit.message%

- -`; - } + return fs.readFileSync(errorPage, 'utf-8'); } /** @@ -93,6 +78,12 @@ function process_config(config, { cwd = process.cwd() } = {}) { validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]); } + if (!fs.existsSync(validated.kit.files.errorPage)) { + validated.kit.files.errorPage = url.fileURLToPath( + new URL('./default-error.html', import.meta.url) + ); + } + return validated; } From 54a670ad1080728bd8fdb1f6b74f6deade807097 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 29 Aug 2022 17:58:57 -0400 Subject: [PATCH 09/16] add some super basic css --- .../kit/src/core/config/default-error.html | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/core/config/default-error.html b/packages/kit/src/core/config/default-error.html index 8b63e78c7c53..eae4dbc89673 100644 --- a/packages/kit/src/core/config/default-error.html +++ b/packages/kit/src/core/config/default-error.html @@ -2,10 +2,55 @@ - Error + %sveltekit.message% + + -

Error - %sveltekit.status%

-

%sveltekit.message%

+
+ %sveltekit.status% +
+

%sveltekit.message%

+
+
From 48a5811970b3c693520a0851673b0819d148ca2a Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 29 Aug 2022 20:14:56 -0400 Subject: [PATCH 10/16] fix test --- packages/kit/src/core/config/index.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js index c39ae72fd304..96a534ffe9d5 100644 --- a/packages/kit/src/core/config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -382,6 +382,7 @@ test('load default config (esm)', async () => { const defaults = get_defaults(cwd + '/'); defaults.kit.version.name = config.kit.version.name; + defaults.kit.files.errorPage = fileURLToPath(new URL('./default-error.html', import.meta.url)); assert.equal(config, defaults); }); From 113cd966b549b8c506b9290ea9aeeaa767ab82f4 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 30 Aug 2022 11:20:33 +0200 Subject: [PATCH 11/16] rename options --- documentation/docs/01-project-structure.md | 2 +- documentation/docs/15-configuration.md | 4 ++-- packages/kit/src/core/config/index.js | 18 +++++++++--------- packages/kit/src/core/config/options.js | 8 ++++++-- packages/kit/types/index.d.ts | 4 ++-- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/documentation/docs/01-project-structure.md b/documentation/docs/01-project-structure.md index d4973bede651..d93e514fd012 100644 --- a/documentation/docs/01-project-structure.md +++ b/documentation/docs/01-project-structure.md @@ -42,7 +42,7 @@ The `src` directory contains the meat of your project. - `%sveltekit.body%` — the markup for a rendered page. Typically this lives inside a `
` or other element, rather than directly inside ``, to prevent bugs caused by browser extensions injecting elements that are then destroyed by the hydration process - `%sveltekit.assets%` — either [`paths.assets`](/docs/configuration#paths), if specified, or a relative path to [`paths.base`](/docs/configuration#base) - `%sveltekit.nonce%` — a [CSP](/docs/configuration#csp) nonce for manually included links and scripts, if used -- `error.html` is the page that is rendered when everything else fails. It can contain the following placeholders: +- `error.html` (optional) is the page that is rendered when everything else fails. It can contain the following placeholders: - `%sveltekit.status%` — the HTTP status - `%sveltekit.message%` — the error message - `hooks.js` (optional) contains your application's [hooks](/docs/hooks) diff --git a/documentation/docs/15-configuration.md b/documentation/docs/15-configuration.md index 8294a8dc9805..81f858280a11 100644 --- a/documentation/docs/15-configuration.md +++ b/documentation/docs/15-configuration.md @@ -40,8 +40,8 @@ const config = { params: 'src/params', routes: 'src/routes', serviceWorker: 'src/service-worker', - template: 'src/app.html', - errorPage: 'src/error.html' + appTemplate: 'src/app.html', + errorTemplate: 'src/error.html' }, inlineStyleThreshold: 0, methodOverride: { diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 92e7ca9926f5..870362fb3bbd 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -10,11 +10,11 @@ import options from './options.js'; * @param {import('types').ValidatedConfig} config */ export function load_template(cwd, config) { - const { template } = config.kit.files; - const relative = path.relative(cwd, template); + const { appTemplate } = config.kit.files; + const relative = path.relative(cwd, appTemplate); - if (fs.existsSync(template)) { - const contents = fs.readFileSync(template, 'utf8'); + if (fs.existsSync(appTemplate)) { + const contents = fs.readFileSync(appTemplate, 'utf8'); // TODO remove this for 1.0 const match = /%svelte\.([a-z]+)%/.exec(contents); @@ -34,7 +34,7 @@ export function load_template(cwd, config) { throw new Error(`${relative} does not exist`); } - return fs.readFileSync(template, 'utf-8'); + return fs.readFileSync(appTemplate, 'utf-8'); } /** @@ -43,8 +43,8 @@ export function load_template(cwd, config) { * @param {import('types').ValidatedConfig} config */ export function load_error_page(config) { - const { errorPage } = config.kit.files; - return fs.readFileSync(errorPage, 'utf-8'); + const { errorTemplate } = config.kit.files; + return fs.readFileSync(errorTemplate, 'utf-8'); } /** @@ -78,8 +78,8 @@ function process_config(config, { cwd = process.cwd() } = {}) { validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]); } - if (!fs.existsSync(validated.kit.files.errorPage)) { - validated.kit.files.errorPage = url.fileURLToPath( + if (!fs.existsSync(validated.kit.files.errorTemplate)) { + validated.kit.files.errorTemplate = url.fileURLToPath( new URL('./default-error.html', import.meta.url) ); } diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index a18287bb4047..4a619faca6b6 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -140,8 +140,12 @@ const options = object( params: string(join('src', 'params')), routes: string(join('src', 'routes')), serviceWorker: string(join('src', 'service-worker')), - template: string(join('src', 'app.html')), - errorPage: string(join('src', 'error.html')) + appTemplate: string(join('src', 'app.html')), + errorTemplate: string(join('src', 'error.html')), + // TODO: remove this for the 1.0 release + template: error( + () => 'config.kit.files.template has been renamed to config.kit.files.appTemplate' + ) }), // TODO: remove this for the 1.0 release diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 76086c75c2f6..780013c63ed4 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -142,8 +142,8 @@ export interface KitConfig { params?: string; routes?: string; serviceWorker?: string; - template?: string; - errorPage?: string; + appTemplate?: string; + errorTemplate?: string; }; inlineStyleThreshold?: number; methodOverride?: { From d507d227d0332538b9767d12139d5f73da73c347 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 30 Aug 2022 11:22:46 +0200 Subject: [PATCH 12/16] remove error.html from create-svelte --- .changeset/quiet-camels-shop.md | 3 +-- .../create-svelte/templates/default/src/error.html | 11 ----------- .../templates/libskeleton/src/error.html | 11 ----------- .../create-svelte/templates/skeleton/src/error.html | 11 ----------- 4 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 packages/create-svelte/templates/default/src/error.html delete mode 100644 packages/create-svelte/templates/libskeleton/src/error.html delete mode 100644 packages/create-svelte/templates/skeleton/src/error.html diff --git a/.changeset/quiet-camels-shop.md b/.changeset/quiet-camels-shop.md index 05eab4f19189..065fbdf5fb97 100644 --- a/.changeset/quiet-camels-shop.md +++ b/.changeset/quiet-camels-shop.md @@ -1,6 +1,5 @@ --- '@sveltejs/kit': patch -'create-svelte': patch --- -[breaking] add error.html page +[breaking] add `error.html` page, rename `kit.config.files.template` to `kit.config.files.appTemplate` diff --git a/packages/create-svelte/templates/default/src/error.html b/packages/create-svelte/templates/default/src/error.html deleted file mode 100644 index 8b63e78c7c53..000000000000 --- a/packages/create-svelte/templates/default/src/error.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Error - - -

Error - %sveltekit.status%

-

%sveltekit.message%

- - diff --git a/packages/create-svelte/templates/libskeleton/src/error.html b/packages/create-svelte/templates/libskeleton/src/error.html deleted file mode 100644 index 8b63e78c7c53..000000000000 --- a/packages/create-svelte/templates/libskeleton/src/error.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Error - - -

Error - %sveltekit.status%

-

%sveltekit.message%

- - diff --git a/packages/create-svelte/templates/skeleton/src/error.html b/packages/create-svelte/templates/skeleton/src/error.html deleted file mode 100644 index 8b63e78c7c53..000000000000 --- a/packages/create-svelte/templates/skeleton/src/error.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Error - - -

Error - %sveltekit.status%

-

%sveltekit.message%

- - From 26a1e5d2aa028aa053b8b9410dae67d93de9de6c Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 30 Aug 2022 12:18:44 +0200 Subject: [PATCH 13/16] fix tests --- packages/kit/src/core/config/index.spec.js | 9 ++++++--- packages/kit/test/apps/options/svelte.config.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/core/config/index.spec.js b/packages/kit/src/core/config/index.spec.js index 96a534ffe9d5..da3274f2d384 100644 --- a/packages/kit/src/core/config/index.spec.js +++ b/packages/kit/src/core/config/index.spec.js @@ -84,8 +84,9 @@ const get_defaults = (prefix = '') => ({ params: join(prefix, 'src/params'), routes: join(prefix, 'src/routes'), serviceWorker: join(prefix, 'src/service-worker'), - template: join(prefix, 'src/app.html'), - errorPage: join(prefix, 'src/error.html') + appTemplate: join(prefix, 'src/app.html'), + errorTemplate: join(prefix, 'src/error.html'), + template: undefined }, headers: undefined, host: undefined, @@ -382,7 +383,9 @@ test('load default config (esm)', async () => { const defaults = get_defaults(cwd + '/'); defaults.kit.version.name = config.kit.version.name; - defaults.kit.files.errorPage = fileURLToPath(new URL('./default-error.html', import.meta.url)); + defaults.kit.files.errorTemplate = fileURLToPath( + new URL('./default-error.html', import.meta.url) + ); assert.equal(config, defaults); }); diff --git a/packages/kit/test/apps/options/svelte.config.js b/packages/kit/test/apps/options/svelte.config.js index accce4d94146..5bef3229bcaf 100644 --- a/packages/kit/test/apps/options/svelte.config.js +++ b/packages/kit/test/apps/options/svelte.config.js @@ -11,7 +11,7 @@ const config = { assets: 'public', lib: 'source/components', routes: 'source/pages', - template: 'source/template.html', + appTemplate: 'source/template.html', // while we specify a path for the service worker, we expect it to not exist in the test serviceWorker: 'source/service-worker' }, From 0779f6b20c0bb243ae6df297f017f7af553c69ab Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 30 Aug 2022 12:21:06 +0200 Subject: [PATCH 14/16] rename internal, too --- packages/kit/src/exports/vite/build/build_server.js | 10 +++++----- packages/kit/src/exports/vite/dev/index.js | 6 +++--- packages/kit/src/runtime/server/page/render.js | 4 ++-- packages/kit/types/internal.d.ts | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js index dd3b00e42f97..7518965e43c7 100644 --- a/packages/kit/src/exports/vite/build/build_server.js +++ b/packages/kit/src/exports/vite/build/build_server.js @@ -25,13 +25,13 @@ import { set_prerendering } from '${runtime}/env.js'; import { set_private_env } from '${runtime}/env-private.js'; import { set_public_env } from '${runtime}/env-public.js'; -const template = ({ head, body, assets, nonce }) => ${s(template) +const app_template = ({ head, body, assets, nonce }) => ${s(template) .replace('%sveltekit.head%', '" + head + "') .replace('%sveltekit.body%', '" + body + "') .replace(/%sveltekit\.assets%/g, '" + assets + "') .replace(/%sveltekit\.nonce%/g, '" + nonce + "')}; -const error_page = ({ status, message }) => ${s(error_page) +const error_template = ({ status, message }) => ${s(error_page) .replace(/%sveltekit\.status%/g, '" + status + "') .replace(/%sveltekit\.message%/g, '" + message + "')}; @@ -83,9 +83,9 @@ export class Server { root, service_worker: ${has_service_worker ? "base + '/service-worker.js'" : 'null'}, router: ${s(config.kit.browser.router)}, - template, - template_contains_nonce: ${template.includes('%sveltekit.nonce%')}, - error_page, + app_template, + app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')}, + error_template, trailing_slash: ${s(config.kit.trailingSlash)} }; } diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js index 4b79f5a86e70..cbefff2fb7cc 100644 --- a/packages/kit/src/exports/vite/dev/index.js +++ b/packages/kit/src/exports/vite/dev/index.js @@ -417,7 +417,7 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { read: (file) => fs.readFileSync(path.join(svelte_config.kit.files.assets, file)), root, router: svelte_config.kit.browser.router, - template: ({ head, body, assets, nonce }) => { + app_template: ({ head, body, assets, nonce }) => { return ( template .replace(/%sveltekit\.assets%/g, assets) @@ -427,8 +427,8 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) { .replace('%sveltekit.body%', () => body) ); }, - template_contains_nonce: template.includes('%sveltekit.nonce%'), - error_page: ({ status, message }) => { + app_template_contains_nonce: template.includes('%sveltekit.nonce%'), + error_template: ({ status, message }) => { return error_page .replace(/%sveltekit\.status%/g, String(status)) .replace(/%sveltekit\.message%/g, message); diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index 9ed1d1e647a1..8a47d0f85456 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -49,7 +49,7 @@ export async function render_response({ throw new Error('Cannot use prerendering if config.kit.csp.mode === "nonce"'); } - if (options.template_contains_nonce) { + if (options.app_template_contains_nonce) { throw new Error('Cannot use prerendering if page template contains %sveltekit.nonce%'); } } @@ -346,7 +346,7 @@ export async function render_response({ // TODO flush chunks as early as we can const html = (await resolve_opts.transformPageChunk({ - html: options.template({ head, body, assets, nonce: /** @type {string} */ (csp.nonce) }), + html: options.app_template({ head, body, assets, nonce: /** @type {string} */ (csp.nonce) }), done: true })) || ''; diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts index 312923d1fe42..21f21f08f6ea 100644 --- a/packages/kit/types/internal.d.ts +++ b/packages/kit/types/internal.d.ts @@ -309,7 +309,7 @@ export interface SSROptions { root: SSRComponent['default']; router: boolean; service_worker?: string; - template({ + app_template({ head, body, assets, @@ -320,8 +320,8 @@ export interface SSROptions { assets: string; nonce: string; }): string; - template_contains_nonce: boolean; - error_page({ message, status }: { message: string; status: number }): string; + app_template_contains_nonce: boolean; + error_template({ message, status }: { message: string; status: number }): string; trailing_slash: TrailingSlash; } From 1871151e102206c60e3d52915c1a9d1af30b4fdd Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 30 Aug 2022 08:12:37 -0400 Subject: [PATCH 15/16] fixes --- packages/kit/src/core/config/index.js | 3 +++ packages/kit/src/runtime/server/utils.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/core/config/index.js b/packages/kit/src/core/config/index.js index 870362fb3bbd..3f5d53dc4f11 100644 --- a/packages/kit/src/core/config/index.js +++ b/packages/kit/src/core/config/index.js @@ -74,6 +74,9 @@ function process_config(config, { cwd = process.cwd() } = {}) { validated.kit.outDir = path.resolve(cwd, validated.kit.outDir); for (const key in validated.kit.files) { + // TODO remove for 1.0 + if (key === 'template') continue; + // @ts-expect-error this is typescript at its stupidest validated.kit.files[key] = path.resolve(cwd, validated.kit.files[key]); } diff --git a/packages/kit/src/runtime/server/utils.js b/packages/kit/src/runtime/server/utils.js index e9e2e2b42cd5..16baabee3edb 100644 --- a/packages/kit/src/runtime/server/utils.js +++ b/packages/kit/src/runtime/server/utils.js @@ -144,7 +144,7 @@ export function data_response(data) { * @param {string} message */ export function static_error_page(options, status, message) { - return new Response(options.error_page({ status, message }), { + return new Response(options.error_template({ status, message }), { headers: { 'content-type': 'text/html; charset=utf-8' }, status }); From 2a3e2af9a1324d88a96c0f1675c68cc886ed4976 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 30 Aug 2022 09:14:00 -0400 Subject: [PATCH 16/16] Update documentation/docs/03-routing.md --- documentation/docs/03-routing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/docs/03-routing.md b/documentation/docs/03-routing.md index f78b45d42ba1..03468fa3308b 100644 --- a/documentation/docs/03-routing.md +++ b/documentation/docs/03-routing.md @@ -190,7 +190,7 @@ If an error occurs during `load`, SvelteKit will render a default error page. Yo

{$page.status}: {$page.error.message}

``` -SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and `src/routes/+error.svelte` before rendering the default error page. If that fails, the contents of a static error page (`src/error.html` by default) will be rendered instead. +SvelteKit will 'walk up the tree' looking for the closest error boundary — if the file above didn't exist it would try `src/routes/blog/+error.svelte` and `src/routes/+error.svelte` before rendering the default error page. If _that_ fails, SvelteKit will bail out and render a static fallback error page, which you can customise by creating a `src/error.html` file. ### +layout