Skip to content

fail on 404 during prerendering #299

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

Merged
merged 10 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ There's also a _huge_ showcase to cover... so let's jump in!

- The new `update` method for `use:enhance` lets you easily get back the default form behavior while augmenting it with your own logic ([docs](https://kit.svelte.dev/docs/form-actions#progressive-enhancement-use-enhance), [#7083](https://github.com/sveltejs/kit/pull/7083) and [#7326](https://github.com/sveltejs/kit/pull/7326))
- `[[optional]]` parameters are now available for routing ([docs](https://kit.svelte.dev/docs/advanced-routing#optional-parameters), [#7051](https://github.com/sveltejs/kit/pull/7051))
- `goto` now has `invalidateAll` to (re-)run all `load` functions belonging to the new active page ([docs](https://kit.svelte.dev/docs/modules#$app-navigation-goto), [#7407](https://github.com/sveltejs/kit/pull/7407))
- `goto` now has `invalidateAll` to (re-)run all `load` functions belonging to the new active page ([docs](https://kit.svelte.dev/docs/$app-navigation#goto), [#7407](https://github.com/sveltejs/kit/pull/7407))
- `config.kit.paths.base` is now used in adapters looking for static assets - fixing 404 issues across `adapter-netlify`, `adapter-vercel`, `adapter-cloudflare`, and `adapter-cloudflare-workers` ([#4448](https://github.com/sveltejs/kit/pull/4448))

### Breaking changes:
Expand Down
6 changes: 3 additions & 3 deletions apps/svelte.dev/content/blog/2023-08-31-view-transitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authorURL: https://geoffrich.net

The [view transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) has been sweeping the web development world lately, and for good reason. It streamlines the process of animating between two page states, which is especially useful for page transitions.

However, until now, you couldn’t easily use this API in a SvelteKit app, since it was difficult to slot into the right place in the navigation lifecycle. SvelteKit 1.24 brought a new [`onNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-onnavigate) lifecycle hook to make view transitions integration much easier – let’s dive in.
However, until now, you couldn’t easily use this API in a SvelteKit app, since it was difficult to slot into the right place in the navigation lifecycle. SvelteKit 1.24 brought a new [`onNavigate`](https://kit.svelte.dev/docs/$app-navigation#onNavigate) lifecycle hook to make view transitions integration much easier – let’s dive in.

## How view transitions work

Expand All @@ -30,9 +30,9 @@ It’s important to note that view transitions is a browser API, not a SvelteKit

## How `onNavigate` works

Before learning how to write view transitions, let's highlight the function that makes it all possible: [`onNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-onnavigate).
Before learning how to write view transitions, let's highlight the function that makes it all possible: [`onNavigate`](https://kit.svelte.dev/docs/$app-navigation#onNavigate).

Until recently, SvelteKit had two navigation lifecycle functions: [`beforeNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-beforenavigate), which fires before a navigation starts, and [`afterNavigate`](https://kit.svelte.dev/docs/modules#$app-navigation-afternavigate), which fires after the page has been updated following a navigation. SvelteKit 1.24 introduces a third: `onNavigate`, which will fire on every navigation, immediately before the new page is rendered. Importantly, it will run _after_ any data loading for the page has completed – since starting a view transition prevents any interaction with the page, we want to start it as late as possible.
Until recently, SvelteKit had two navigation lifecycle functions: [`beforeNavigate`](https://kit.svelte.dev/docs/$app-navigation#beforeNavigate), which fires before a navigation starts, and [`afterNavigate`](https://kit.svelte.dev/docs/$app-navigation#afterNavigate), which fires after the page has been updated following a navigation. SvelteKit 1.24 introduces a third: `onNavigate`, which will fire on every navigation, immediately before the new page is rendered. Importantly, it will run _after_ any data loading for the page has completed – since starting a view transition prevents any interaction with the page, we want to start it as late as possible.

You can also return a promise from `onNavigate`, which will suspend the navigation until it resolves. This will let us wait to complete the navigation until the view transition has started.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ title: Introduction

SvelteKit is a framework for rapidly developing robust, performant web applications using [Svelte](https://svelte.dev/). If you're coming from React, SvelteKit is similar to Next. If you're coming from Vue, SvelteKit is similar to Nuxt.

To learn more about the kinds of applications you can build with SvelteKit, see the [FAQ](/docs/faq#what-can-i-make-with-sveltekit).
To learn more about the kinds of applications you can build with SvelteKit, see the [FAQ](faq#what-can-i-make-with-sveltekit).

## What is Svelte?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ You'll also find common files like `.gitignore` and `.npmrc` (and `.prettierrc`

The `src` directory contains the meat of your project. Everything except `src/routes` and `src/app.html` is optional.

- `lib` contains your library code (utilities and components), which can be imported via the [`$lib`](modules#$lib) alias, or packaged up for distribution using [`svelte-package`](packaging)
- `lib` contains your library code (utilities and components), which can be imported via the [`$lib`]($lib) alias, or packaged up for distribution using [`svelte-package`](packaging)
- `server` contains your server-only library code. It can be imported by using the [`$lib/server`](server-only-modules) alias. SvelteKit will prevent you from importing these in client code.
- `params` contains any [param matchers](advanced-routing#matching) your app needs
- `routes` contains the [routes](routing) of your application. You can also colocate other components that are only used within a single route here
Expand Down Expand Up @@ -83,7 +83,7 @@ This file (or `jsconfig.json`, if you prefer type-checked `.js` files over `.ts`

### vite.config.js

A SvelteKit project is really just a [Vite](https://vitejs.dev) project that uses the [`@sveltejs/kit/vite`](modules#sveltejs-kit-vite) plugin, along with any other [Vite configuration](https://vitejs.dev/config/).
A SvelteKit project is really just a [Vite](https://vitejs.dev) project that uses the [`@sveltejs/kit/vite`](@sveltejs-kit-vite) plugin, along with any other [Vite configuration](https://vitejs.dev/config/).

## Other files

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ An instance of [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Res

### Headers

The [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) interface allows you to read incoming `request.headers` and set outgoing `response.headers`. For example, you can get the `request.headers` as shown below, and use the [`json` convenience function](modules#sveltejs-kit-json) to send modified `response.headers`:
The [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) interface allows you to read incoming `request.headers` and set outgoing `response.headers`. For example, you can get the `request.headers` as shown below, and use the [`json` convenience function](@sveltejs-kit#json) to send modified `response.headers`:

```js
// @errors: 2461
Expand Down Expand Up @@ -78,7 +78,7 @@ Most of the time, your endpoints will return complete data, as in the `userAgent

## URL APIs

URLs are represented by the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) interface, which includes useful properties like `origin` and `pathname` (and, in the browser, `hash`). This interface shows up in various places — `event.url` in [hooks](hooks) and [server routes](routing#server), [`$page.url`](modules#$app-stores) in [pages](routing#page), `from` and `to` in [`beforeNavigate` and `afterNavigate`](modules#$app-navigation) and so on.
URLs are represented by the [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) interface, which includes useful properties like `origin` and `pathname` (and, in the browser, `hash`). This interface shows up in various places — `event.url` in [hooks](hooks) and [server routes](routing#server), [`$page.url`]($app-stores) in [pages](routing#page), `from` and `to` in [`beforeNavigate` and `afterNavigate`]($app-navigation) and so on.

### URLSearchParams

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ You can find more information about these in [page options](page-options).

### +page.server.js

If your `load` function can only run on the server — for example, if it needs to fetch data from a database or you need to access private [environment variables](modules#$env-static-private) like API keys — then you can rename `+page.js` to `+page.server.js` and change the `PageLoad` type to `PageServerLoad`.
If your `load` function can only run on the server — for example, if it needs to fetch data from a database or you need to access private [environment variables]($env-static-private) like API keys — then you can rename `+page.js` to `+page.server.js` and change the `PageLoad` type to `PageServerLoad`.

```js
/// file: src/routes/blog/[slug]/+page.server.js
Expand Down Expand Up @@ -283,7 +283,7 @@ export function GET({ url }) {

The first argument to `Response` can be a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), making it possible to stream large amounts of data or create server-sent events (unless deploying to platforms that buffer responses, like AWS Lambda).

You can use the [`error`](modules#sveltejs-kit-error), [`redirect`](modules#sveltejs-kit-redirect) and [`json`](modules#sveltejs-kit-json) methods from `@sveltejs/kit` for convenience (but you don't have to).
You can use the [`error`](@sveltejs-kit#error), [`redirect`](@sveltejs-kit#redirect) and [`json`](@sveltejs-kit#json) methods from `@sveltejs/kit` for convenience (but you don't have to).

If an error is thrown (either `error(...)` or an unexpected error), the response will be a JSON representation of the error or a fallback error page — which can be customised via `src/error.html` — depending on the `Accept` header. The [`+error.svelte`](#error) component will _not_ be rendered in this case. You can read more about error handling [here](errors).

Expand Down Expand Up @@ -390,7 +390,7 @@ You can read more about omitting `$types` in our [blog post](https://svelte.dev/

Any other files inside a route directory are ignored by SvelteKit. This means you can colocate components and utility modules with the routes that need them.

If components and modules are needed by multiple routes, it's a good idea to put them in [`$lib`](modules#$lib).
If components and modules are needed by multiple routes, it's a good idea to put them in [`$lib`]($lib).

## Further reading

Expand Down
16 changes: 8 additions & 8 deletions apps/svelte.dev/content/docs/kit/20-core-concepts/20-load.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ export async function load({ params, parent }) {

## Errors

If an error is thrown during `load`, the nearest [`+error.svelte`](routing#error) will be rendered. For [_expected_](/docs/errors#expected-errors) errors, use the `error` helper from `@sveltejs/kit` to specify the HTTP status code and an optional message:
If an error is thrown during `load`, the nearest [`+error.svelte`](routing#error) will be rendered. For [_expected_](errors#expected-errors) errors, use the `error` helper from `@sveltejs/kit` to specify the HTTP status code and an optional message:

```js
/// file: src/routes/admin/+layout.server.js
Expand Down Expand Up @@ -430,7 +430,7 @@ export function load({ locals }) {

Calling `error(...)` will throw an exception, making it easy to stop execution from inside helper functions.

If an [_unexpected_](/docs/errors#unexpected-errors) error is thrown, SvelteKit will invoke [`handleError`](hooks#shared-hooks-handleerror) and treat it as a 500 Internal Error.
If an [_unexpected_](errors#unexpected-errors) error is thrown, SvelteKit will invoke [`handleError`](hooks#shared-hooks-handleerror) and treat it as a 500 Internal Error.

> [In SvelteKit 1.x](migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you) you had to `throw` the error yourself

Expand Down Expand Up @@ -463,7 +463,7 @@ export function load({ locals }) {

> Don't use `redirect()` inside a `try {...}` block, as the redirect will immediately trigger the catch statement.

In the browser, you can also navigate programmatically outside of a `load` function using [`goto`](modules#$app-navigation-goto) from [`$app.navigation`](modules#$app-navigation).
In the browser, you can also navigate programmatically outside of a `load` function using [`goto`]($app-navigation#goto) from [`$app.navigation`]($app-navigation).

> [In SvelteKit 1.x](migrating-to-sveltekit-2#redirect-and-error-are-no-longer-thrown-by-you) you had to `throw` the `redirect` yourself

Expand Down Expand Up @@ -615,7 +615,7 @@ export async function load({ untrack, url }) {

### Manual invalidation

You can also rerun `load` functions that apply to the current page using [`invalidate(url)`](modules#$app-navigation-invalidate), which reruns all `load` functions that depend on `url`, and [`invalidateAll()`](modules#$app-navigation-invalidateall), which reruns every `load` function. Server load functions will never automatically depend on a fetched `url` to avoid leaking secrets to the client.
You can also rerun `load` functions that apply to the current page using [`invalidate(url)`]($app-navigation#invalidate), which reruns all `load` functions that depend on `url`, and [`invalidateAll()`]($app-navigation#invalidateAll), which reruns every `load` function. Server load functions will never automatically depend on a fetched `url` to avoid leaking secrets to the client.

A `load` function depends on `url` if it calls `fetch(url)` or `depends(url)`. Note that `url` can be a custom identifier that starts with `[a-z]:`:

Expand Down Expand Up @@ -665,12 +665,12 @@ To summarize, a `load` function will rerun in the following situations:
- It calls `url.searchParams.get(...)`, `url.searchParams.getAll(...)` or `url.searchParams.has(...)` and the parameter in question changes. Accessing other properties of `url.searchParams` will have the same effect as accessing `url.search`.
- It calls `await parent()` and a parent `load` function reran
- A child `load` function calls `await parent()` and is rerunning, and the parent is a server load function
- It declared a dependency on a specific URL via [`fetch`](#making-fetch-requests) (universal load only) or [`depends`](types#public-types-loadevent), and that URL was marked invalid with [`invalidate(url)`](modules#$app-navigation-invalidate)
- All active `load` functions were forcibly rerun with [`invalidateAll()`](modules#$app-navigation-invalidateall)
- It declared a dependency on a specific URL via [`fetch`](#making-fetch-requests) (universal load only) or [`depends`](types#public-types-loadevent), and that URL was marked invalid with [`invalidate(url)`]($app-navigation#invalidate)
- All active `load` functions were forcibly rerun with [`invalidateAll()`]($app-navigation#invalidateAll)

`params` and `url` can change in response to a `<a href="..">` link click, a [`<form>` interaction](form-actions#get-vs-post), a [`goto`](modules#$app-navigation-goto) invocation, or a [`redirect`](modules#sveltejs-kit-redirect).
`params` and `url` can change in response to a `<a href="..">` link click, a [`<form>` interaction](form-actions#get-vs-post), a [`goto`]($app-navigation#goto) invocation, or a [`redirect`](@sveltejs-kit#redirect).

Note that rerunning a `load` function will update the `data` prop inside the corresponding `+layout.svelte` or `+page.svelte`; it does _not_ cause the component to be recreated. As a result, internal state is preserved. If this isn't what you want, you can reset whatever you need to reset inside an [`afterNavigate`](modules#$app-navigation-afternavigate) callback, and/or wrap your component in a [`{#key ...}`](https://svelte.dev/docs#template-syntax-key) block.
Note that rerunning a `load` function will update the `data` prop inside the corresponding `+layout.svelte` or `+page.svelte`; it does _not_ cause the component to be recreated. As a result, internal state is preserved. If this isn't what you want, you can reset whatever you need to reset inside an [`afterNavigate`]($app-navigation#afterNavigate) callback, and/or wrap your component in a [`{#key ...}`](https://svelte.dev/docs#template-syntax-key) block.

## Implications for authentication

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const prerender = 'auto';

The prerenderer will start at the root of your app and generate files for any prerenderable pages or `+server.js` routes it finds. Each page is scanned for `<a>` elements that point to other pages that are candidates for prerendering — because of this, you generally don't need to specify which pages should be accessed. If you _do_ need to specify which pages should be accessed by the prerenderer, you can do so with [`config.kit.prerender.entries`](configuration#prerender), or by exporting an [`entries`](#entries) function from your dynamic route.

While prerendering, the value of `building` imported from [`$app/environment`](modules#$app-environment) will be `true`.
While prerendering, the value of `building` imported from [`$app/environment`]($app-environment) will be `true`.

### Prerendering server routes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ If you're not using SSR, then there's no risk of accidentally exposing one user'

## Using stores with context

You might wonder how we're able to use `$page.data` and other [app stores](modules#$app-stores) if we can't use our own stores. The answer is that app stores on the server use Svelte's [context API](https://learn.svelte.dev/tutorial/context-api) — the store is attached to the component tree with `setContext`, and when you subscribe you retrieve it with `getContext`. We can do the same thing with our own stores:
You might wonder how we're able to use `$page.data` and other [app stores]($app-stores) if we can't use our own stores. The answer is that app stores on the server use Svelte's [context API](https://learn.svelte.dev/tutorial/context-api) — the store is attached to the component tree with `setContext`, and when you subscribe you retrieve it with `getContext`. We can do the same thing with our own stores:

```svelte
<!--- file: src/routes/+layout.svelte --->
Expand Down Expand Up @@ -155,7 +155,7 @@ Instead, we need to make the value [_reactive_](https://learn.svelte.dev/tutoria
</script>
```

> If your code in `onMount` and `onDestroy` has to run again after navigation you can use [afterNavigate](modules#$app-navigation-afternavigate) and [beforeNavigate](modules#$app-navigation-beforenavigate) respectively.
> If your code in `onMount` and `onDestroy` has to run again after navigation you can use [afterNavigate]($app-navigation#afterNavigate) and [beforeNavigate]($app-navigation#beforeNavigate) respectively.

Reusing components like this means that things like sidebar scroll state are preserved, and you can easily animate between changing values. In the case that you do need to completely destroy and remount a component on navigation, you can use this pattern:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Secondly, an _adapter_ takes this production build and tunes it for your target

## During the build

SvelteKit will load your `+page/layout(.server).js` files (and all files they import) for analysis during the build. Any code that should _not_ be executed at this stage must check that `building` from [`$app/environment`](modules#$app-environment) is `false`:
SvelteKit will load your `+page/layout(.server).js` files (and all files they import) for analysis during the build. Any code that should _not_ be executed at this stage must check that `building` from [`$app/environment`]($app-environment) is `false`:

```diff
+import { building } from '$app/environment';
Expand Down
Loading
Loading