Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] more info about prerendering errors and new strict option #7264

Merged
merged 10 commits into from Oct 18, 2022
6 changes: 6 additions & 0 deletions .changeset/tame-bats-tell.md
@@ -0,0 +1,6 @@
---
'@sveltejs/adapter-static': patch
'@sveltejs/kit': patch
---

[fix] more info about prerendering errors
6 changes: 4 additions & 2 deletions documentation/docs/13-page-options.md
Expand Up @@ -72,13 +72,15 @@ Note that this will disable client-side routing for any navigation from this pag

#### Troubleshooting

If you encounter an error like 'The following routes were marked as prerenderable, but were not prerendered' it's because the route in question (or a parent layout, if it's a page) has `export const prerender = true` but the page wasn't actually prerendered.
If you encounter an error like 'The following routes were marked as prerenderable, but were not prerendered' it's because the route in question (or a parent layout, if it's a page) has `export const prerender = true` but the page wasn't actually prerendered (because they were not reached by the prerendering crawler).

Since these routes cannot be dynamically server-rendered, this will cause errors when people try to access the route in question. There are two ways to fix it:

* Ensure that SvelteKit can find the route by following links from [`config.kit.prerender.entries`](/docs/configuration#prerender). The pages containing the links (e.g. your `/` page) must _themselves_ be prerenderable, or they will be ignored
* Ensure that SvelteKit can find the route by following links from [`config.kit.prerender.entries`](/docs/configuration#prerender). Add links to dynamic routes (i.e. pages with `[parameters]` ) to this option if they are not found through crawling the other entry points, else they are not prerendered because SvelteKit doesn't know what value the parameters should have. The pages containing the links (e.g. your `/` page) must _themselves_ be prerenderable, or they will be ignored.
dummdidumm marked this conversation as resolved.
Show resolved Hide resolved
* Change `export const prerender = true` to `export const prerender = 'auto'`. Routes with `'auto'` can be dynamically server rendered

If you are using `@sveltejs/adapter-static`, _all_ pages (and endpoints, if any) must be prerendered, otherwise you need to use a different adapter.

Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
### ssr

Normally, SvelteKit renders your page on the server first and sends that HTML to the client where it's hydrated. If you set `ssr` to `false`, it renders an empty 'shell' page instead. This is useful if your page is unable to be rendered on the server, but in most situations it's not recommended ([see appendix](/docs/appendix#ssr)).
Expand Down
2 changes: 1 addition & 1 deletion documentation/docs/16-configuration.md
Expand Up @@ -252,7 +252,7 @@ See [Prerendering](/docs/page-options#prerender). An object containing zero or m
- `concurrency` — how many pages can be prerendered simultaneously. JS is single-threaded, but in cases where prerendering performance is network-bound (for example loading content from a remote CMS) this can speed things up by processing other tasks while waiting on the network response
- `crawl` — determines whether SvelteKit should find pages to prerender by following links from the seed page(s)
- `enabled` — set to `false` to disable prerendering altogether
- `entries` — an array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all non-dynamic routes (i.e. pages with no `[parameters]` )
- `entries` — an array of pages to prerender, or start crawling from (if `crawl: true`). The `*` string includes all non-dynamic routes (i.e. pages with no `[parameters]`, because SvelteKit doesn't know what value the parameters should have)
- `onError`

- `'fail'` — (default) fails the build when a routing error is encountered when following a link
Expand Down
20 changes: 16 additions & 4 deletions packages/adapter-static/index.js
Expand Up @@ -26,11 +26,23 @@ export default function (options) {

if (dynamic_routes.length > 0) {
const prefix = path.relative('.', builder.config.kit.files.routes);
const config_option =
dummdidumm marked this conversation as resolved.
Show resolved Hide resolved
dynamic_routes.some((route) => route.includes('[')) &&
JSON.stringify(builder.config.kit.prerender.entries) === '["*"]'
? ' - adjust the `prerender.entries` config option (routes with parameters are not part of entry points by default) — see https://kit.svelte.dev/docs/configuration#prerender for more info.\n'
: '';

builder.log.error(
`@sveltejs/adapter-static: all routes must be fully prerenderable (unless using the 'fallback' option — see https://github.com/sveltejs/kit/tree/master/packages/adapter-static#spa-mode). Try adding \`export const prerender = true\` to your root +layout.js/.ts file — see https://kit.svelte.dev/docs/page-options#prerender for more details`
);
builder.log.error(
dynamic_routes.map((id) => ` - ${path.posix.join(prefix, id)}`).join('\n')
`@sveltejs/adapter-static: all routes must be fully prerenderable, but found the following routes that are dynamic:
${dynamic_routes.map((id) => ` - ${path.posix.join(prefix, id)}`).join('\n')}

You have the following options:
- set the 'fallback' option — see https://github.com/sveltejs/kit/tree/master/packages/adapter-static#spa-mode for more info
- add \`export const prerender = true\` to your root \`+layout.js/.ts\` or \`+layout.server.js/.ts\` file. This will try to prerender all pages.
- add \`export const prerender = true\` to your \`+server.js/ts\` files (if any) that are not called through pages (else these are not prerendered).
Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
${config_option}
If this doesn't help, you may need to use a different adapter. @sveltejs/adapter-static can only be used for sites that don't need a backend (i.e. a static file server is enough).
See https://kit.svelte.dev/docs/page-options#prerender for more details`
);
throw new Error('Encountered dynamic routes');
}
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/core/prerender/prerender.js
Expand Up @@ -431,9 +431,9 @@ export async function prerender() {

if (not_prerendered.length > 0) {
throw new Error(
`The following routes were marked as prerenderable, but were not prerendered:\n${not_prerendered.map(
`The following routes were marked as prerenderable, but were not prerendered, because they were not found while crawling your app:\n${not_prerendered.map(
Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
(id) => ` - ${id}`
)}\n\nSee https://kit.svelte.dev/docs/page-options#prerender-troubleshooting for more info`
)}\n\nSee https://kit.svelte.dev/docs/page-options#prerender-troubleshooting for info on how to solve this`
);
}

Expand Down
7 changes: 6 additions & 1 deletion packages/kit/src/utils/filesystem.js
Expand Up @@ -6,7 +6,12 @@ export function mkdirp(dir) {
try {
fs.mkdirSync(dir, { recursive: true });
} catch (/** @type {any} */ e) {
if (e.code === 'EEXIST') return;
if (e.code === 'EEXIST') {
if (!fs.statSync(dir).isDirectory()) {
throw new Error(`Cannot create directory ${dir}, a file already exists at this position`);
}
return;
}
throw e;
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/test/build-errors/prerender.spec.js
Expand Up @@ -11,7 +11,7 @@ test('prerenderable routes must be prerendered', () => {
stdio: 'pipe',
timeout: 15000
}),
/The following routes were marked as prerenderable, but were not prerendered:\r?\n - \[x\]/gs
/The following routes were marked as prerenderable, but were not prerendered, because they were not found while crawling your app:\r?\n - \[x\]/gs
Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
);
});

Expand Down