Unable to entirely disable prerendering
See original GitHub issueDescribe the bug
Hi,
Forgive me if I’ve missed something! I’d like to run SvelteKit as a SSR-and-CSR solution, with no build-time prerendering.
From the docs, I can disable prerendering routes by adding a export const prerender = false; annotation to the top-level +layout.js. This seems to work.
I can also prevent the build process from crawling for entries to prerender (svelte.config.js):
// Disable prerendering, as this is a dynamic app
prerender: {
crawl: false,
entries: [],
},
However, despite these two settings, I am still seeing an attempt to prerender when I run vite build:
#13 38.79 handleFeatureFlags (hooks/featureFlags.js) running for URL: http://sveltekit-prerender/[fallback]
...
#13 58.82 TypeError: Cannot destructure property 'CI_ENVIRONMENT_NAME' of 'env' as it is undefined.
#13 58.82 at reportError (file:///app/server/.svelte-kit/output/server/chunks/hooks.server.js:954:32)
#13 58.82 at Object.handleError (file:///app/server/.svelte-kit/output/server/chunks/hooks.server.js:1011:27)
#13 58.82 at Object.handle_error (file:///app/server/.svelte-kit/output/server/index.js:2369:35)
#13 58.82 at handle_error_and_jsonify (file:///app/server/.svelte-kit/output/server/index.js:243:20)
#13 58.82 at handle_fatal_error (file:///app/server/.svelte-kit/output/server/index.js:226:22)
#13 58.82 at respond (file:///app/server/.svelte-kit/output/server/index.js:2196:18)
#13 58.82 at async prerender (file:///app/server/node_modules/@sveltejs/kit/src/core/prerender/prerender.js:439:19)
...
#13 58.85 [vite-plugin-svelte-kit] Prerendering failed with code 1
#13 58.85 error during build:
#13 58.85 Error: Prerendering failed with code 1
#13 58.85 at ChildProcess.<anonymous> (file:///app/server/node_modules/@sveltejs/kit/src/exports/vite/index.js:462:15)
#13 58.85 at ChildProcess.emit (node:events:513:28)
#13 58.85 at ChildProcess.emit (node:domain:489:12)
#13 58.85 at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
I’ve tracked this down to this code block:
const rendered = await server.respond(new Request(config.prerender.origin + '/[fallback]'), {
getClientAddress,
prerendering: {
fallback: true,
dependencies: new Map()
}
});
const file = `${config.outDir}/output/prerendered/fallback.html`;
mkdirp(dirname(file));
writeFileSync(file, await rendered.text());
Whereas prerendering known routes and other entries can be disabled with the above config, there doesn’t seem to be a way to disable the rendering of the fallback.html file. This is a problem for anyone who wants to ship code in server hooks which doesn’t work in the environment in which vite build is run.
Would it be possible to allow this fallback prerendering to be disabled? If not, it’d be great to understand why it’s important (somewhere in the documentation), and I guess the only option is for the hooks to make use of $app/environment.building or similar to only conditionally run their logic?
Reproduction
https://stackblitz.com/edit/sveltejs-kit-template-default-x9vwcp
This project adds the following changes to the default https://node.new/sveltekit:
- adds
export const prerender = false;tosrc/routes/+layout.js - removes
export const prerender = true;from all other routes - disables prerender crawling in
svelte.config.js:
const config = {
kit: {
adapter: adapter(),
// Disable prerendering, as this is a dynamic app
prerender: {
crawl: false,
entries: []
}
}
};
- adds a
hooks.server.jsfile which relies on environment variables:
export async function handle({ event, resolve }) {
const thisWillFail = new URL(process.env.UNDECLARED_ENV_VAR_DURING_BUILD);
const response = await resolve(event);
return response;
}
export async function handleError({ error, event }) {
const thisWillFail = new URL(process.env.UNDECLARED_ENV_VAR_DURING_BUILD);
return error;
}
- modifies the
npm run devscript to be"UNDECLARED_ENV_VAR_DURING_BUILD='http://testing' vite dev"so that local dev works
Running npm run build shows that an attempt to prerender the URL http://sveltekit-prerender/[fallback] is still made, and since the environment variable is not declared, the hooks cause the build to fail:
...
.svelte-kit/output/server/chunks/hooks.server.js 0.37 KiB
handle hook running for URL: http://sveltekit-prerender/[fallback]
TypeError [ERR_INVALID_URL]: Invalid URL
...
input: 'undefined',
code: 'ERR_INVALID_URL'
}
[vite-plugin-svelte-kit] Prerendering failed with code 1
error during build:
Error: Prerendering failed with code 1
...
One solution I’ve found for this is the following, in hooks.server.js:
import {building} from '$app/environment';
export const handle = building
? sequence()
: sequence(
handleLoggingAndMonitoring,
handleCookieParsing,
handleFeatureFlags,
handleEnvVars,
handleImageUrls,
handleApiRequest,
handleApiServices,
handleSecurityHeaders
);
Is this the recommended approach? If so, it still seems odd to me that I’m unable to disable prerendering across the board.
Logs
No response
System Info
System:
OS: macOS 12.4
CPU: (8) arm64 Apple M1 Pro
Memory: 212.80 MB / 32.00 GB
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 16.18.0 - /usr/local/bin/node
Yarn: 1.22.10 - /usr/local/bin/yarn
npm: 8.19.2 - /usr/local/bin/npm
Watchman: 2022.11.14.00 - /opt/homebrew/bin/watchman
Browsers:
Chrome: 107.0.5304.110
Chrome Canary: 110.0.5443.0
Firefox: 105.0.3
Safari: 15.5
npmPackages:
@sveltejs/adapter-node: ^1.0.0-next.101 => 1.0.0-next.101
@sveltejs/kit: ^1.0.0-next.570 => 1.0.0-next.570
svelte: ^3.53.1 => 3.53.1
Severity
blocking all usage of SvelteKit
Additional Information
No response
Issue Analytics
- State:
- Created 10 months ago
- Reactions:1
- Comments:13 (11 by maintainers)

Top Related StackOverflow Question
Thanks for your thoughts, both. I’m aware of the
$envnamespace, but I don’t currently have the time to migrate over - we’re up against the wire trying to upgrade to the RC of SvelteKit and just ‘make things work’. The single workaround above (disabling our hooks whenbuildingistrue) works for the time being, and I’ll reference this ticket to see if anything more elegant appears in the codebase in future.I want to reiterate my thanks to you both (@Rich-Harris and @dummdidumm) and the wider team. Kit is a fantastic piece of work, and your recent breaking changes are so much better for ergonomics. Well done for being brave and sticking to doing the best you can for v1. Exciting days are very close now.
We’re running a “SPA-mode” setup. Prerendering disabled as much as we can with
prerender.entries = [], a fallback page to run the app, nginx set up to set the fallback page in the normal way for such things, and whatever else is necessary to make that work. I think theangularimport errors were still there before; they just didn’t matter because the try/catch statement was swallowing them.Anyway, I think the details are moot for now, since I just confirmed that it does work to deep-import the specific files that we need so that
angulardoesn’t get imported from the.jsfiles. I think I’m good now. Thanks!It’s been a long process getting Angular slowly stripped out of our 8-year-old app, can’t wait to get it finished and be 100% on SvelteKit 😃