Skip to content

Commit

Permalink
Change config prerender.force to prerender.onError
Browse files Browse the repository at this point in the history
fixes sveltejs#1940

- Changing from `force` to `onError` gives a somewhat more descriptive
  name to the option.
- Using the strings "fail" and "continue" further clarifies what the
  option does.
- Providing your own function to deal with an error allows for
  fine-tuning which errors fail the build and which do not.

The original ticket suggested that the custom function return a boolean,
but after seeing the implementation of the error handler in svelteKit, I
thought it more fitting to just allow it the exact same API: throw if
you want the build to fail.
  • Loading branch information
happycollision committed Jul 25, 2021
1 parent 68c3906 commit 3e839b0
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-guests-collect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Remove the `prerender.force` option in favor of `prerender.onError`
27 changes: 25 additions & 2 deletions documentation/docs/14-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const config = {
prerender: {
crawl: true,
enabled: true,
force: false,
onError: 'fail',
pages: ['*']
},
router: true,
Expand Down Expand Up @@ -148,7 +148,30 @@ See [Prerendering](#ssr-and-javascript-prerender). An object containing zero or

- `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
- `force` — if `true`, a page that fails to render will _not_ cause the entire build to fail
- `onError`

- `"fail"` — (default) fails the build when a routing error is encountered when following a link
- `"continue"` — allows the build to continue, despite routing errors
- function — you can use the `errorDetails` to determine whether or not to `throw`, thereby failing the build.

```ts
/** @type {import('@sveltejs/kit').PrerenderErrorHandler} */
const handleError = ({ status, path, parent, verb }) => {
if (path.startsWith('/blog')) throw new Error('Missing a blog page!');
console.warn(`${status} ${path}${parent ? ` (${verb} from ${parent})` : ''}`);

export default {
kit: {
adapter: static(),
target: '#svelte',
prerender: {
onError: handleError
}
}
};
};
```

- `pages`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]` )

### router
Expand Down
33 changes: 25 additions & 8 deletions packages/kit/src/core/adapt/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,31 @@ export async function prerender({ cwd, out, log, config, build_data, fallback, a
read: (file) => readFileSync(join(config.kit.files.assets, file))
});

/** @type {(status: number, path: string, parent: string | null, verb: string) => void} */
const error = config.kit.prerender.force
? (status, path, parent, verb) => {
log.error(`${status} ${path}${parent ? ` (${verb} from ${parent})` : ''}`);
}
: (status, path, parent, verb) => {
throw new Error(`${status} ${path}${parent ? ` (${verb} from ${parent})` : ''}`);
};
/** @typedef {((status: number, path: string, parent: string | null, verb: string) => void | never)} InternalErrorHandler */
/** @type {InternalErrorHandler} */
const error = (function () {
const { onError } = config.kit.prerender;

/** @type {(...details: Parameters<InternalErrorHandler> ) => string} */
const detailsToString = (status, path, parent, verb) =>
`${status} ${path}${parent ? ` (${verb} from ${parent})` : ''}`;

switch (onError) {
case 'continue':
/** @type {InternalErrorHandler} */
return (status, path, parent, verb) => {
log.error(detailsToString(status, path, parent, verb));
};
case 'fail':
/** @type {InternalErrorHandler} */
return (status, path, parent, verb) => {
throw new Error(detailsToString(status, path, parent, verb));
};
default:
/** @type {InternalErrorHandler} */
return (status, path, parent, verb) => onError({ status, path, parent, verb });
}
})();

const files = new Set([...build_data.static, ...build_data.client]);

Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/core/config/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test('fills in defaults', () => {
prerender: {
crawl: true,
enabled: true,
force: false,
onError: 'fail',
pages: ['*']
},
router: true,
Expand Down Expand Up @@ -150,7 +150,7 @@ test('fills in partial blanks', () => {
prerender: {
crawl: true,
enabled: true,
force: false,
onError: 'fail',
pages: ['*']
},
router: true,
Expand Down
12 changes: 11 additions & 1 deletion packages/kit/src/core/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,17 @@ const options = {
children: {
crawl: expect_boolean(true),
enabled: expect_boolean(true),
force: expect_boolean(false),
onError: {
type: 'leaf',
default: 'fail',
validate: (option, keypath) => {
if (typeof option === 'function') return option;
if (['continue', 'fail'].includes(option)) return option;
throw new Error(
`${keypath} should be either a custom function or one of "continue" or "fail"`
);
}
},
pages: {
type: 'leaf',
default: ['*'],
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/core/config/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async function testLoadDefaultConfig(path) {
exclude: []
},
paths: { base: '', assets: '/.' },
prerender: { crawl: true, enabled: true, force: false, pages: ['*'] },
prerender: { crawl: true, enabled: true, onError: 'fail', pages: ['*'] },
router: true,
ssr: true,
target: null,
Expand Down
9 changes: 8 additions & 1 deletion packages/kit/types/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ export type Config = {
preprocess?: any;
};

export type PrerenderErrorHandler = (errorDetails: {
status: number;
path: string;
parent: string | null;
verb: string;
}) => void | never;

export type ValidatedConfig = {
compilerOptions: any;
extensions: string[];
Expand Down Expand Up @@ -117,7 +124,7 @@ export type ValidatedConfig = {
prerender: {
crawl: boolean;
enabled: boolean;
force: boolean;
onError: 'fail' | 'continue' | PrerenderErrorHandler;
pages: string[];
};
router: boolean;
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import './ambient-modules';

export { Adapter, AdapterUtils, Config, ValidatedConfig } from './config';
export { Adapter, AdapterUtils, Config, ValidatedConfig, PrerenderErrorHandler } from './config';
export { EndpointOutput, RequestHandler } from './endpoint';
export { ErrorLoad, ErrorLoadInput, Load, LoadInput, LoadOutput, Page } from './page';
export {
Expand Down

0 comments on commit 3e839b0

Please sign in to comment.