Skip to content

Commit

Permalink
Sync kit docs (#1105)
Browse files Browse the repository at this point in the history
sync kit docs

Co-authored-by: Rich-Harris <[email protected]>
  • Loading branch information
github-actions[bot] and Rich-Harris authored Jan 20, 2025
1 parent e4cdbe6 commit 78f401b
Show file tree
Hide file tree
Showing 14 changed files with 245 additions and 91 deletions.
34 changes: 28 additions & 6 deletions apps/svelte.dev/content/docs/kit/20-core-concepts/10-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Pages can receive data from `load` functions via the `data` prop.
```svelte
<!--- file: src/routes/blog/[slug]/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
</script>
Expand All @@ -52,7 +52,9 @@ Pages can receive data from `load` functions via the `data` prop.
```

> [!LEGACY]
> In Svelte 4, you'd use `export let data` instead
> `PageProps` was added in 2.16.0. In earlier versions, you had to type the `data` property manually with `PageData` instead, see [$types](#\$types).
>
> In Svelte 4, you'd use `export let data` instead.
> [!NOTE] SvelteKit uses `<a>` elements to navigate between routes, rather than a framework-specific `<Link>` component.
Expand Down Expand Up @@ -213,7 +215,7 @@ We can create a layout that only applies to pages below `/settings` (while inher
```svelte
<!--- file: src/routes/settings/+layout.svelte --->
<script>
/** @type {{ data: import('./$types').LayoutData, children: import('svelte').Snippet }} */
/** @type {import('./$types').LayoutProps} */
let { data, children } = $props();
</script>
Expand All @@ -228,6 +230,9 @@ We can create a layout that only applies to pages below `/settings` (while inher
{@render children()}
```

> [!LEGACY]
> `LayoutProps` was added in 2.16.0. In earlier versions, you had to [type the properties manually instead](#\$types).
You can see how `data` is populated by looking at the `+layout.js` example in the next section just below.

By default, each layout inherits the layout above it. Sometimes that isn't what you want - in this case, [advanced layouts](advanced-routing#Advanced-layouts) can help you.
Expand Down Expand Up @@ -256,7 +261,7 @@ Data returned from a layout's `load` function is also available to all its child
```svelte
<!--- file: src/routes/settings/profile/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
console.log(data.sections); // [{ slug: 'profile', title: 'Profile' }, ...]
Expand Down Expand Up @@ -389,16 +394,33 @@ export async function fallback({ request }) {
Throughout the examples above, we've been importing types from a `$types.d.ts` file. This is a file SvelteKit creates for you in a hidden directory if you're using TypeScript (or JavaScript with JSDoc type annotations) to give you type safety when working with your root files.
For example, annotating `let { data } = $props()` with `PageData` (or `LayoutData`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
For example, annotating `let { data } = $props()` with `PageProps` (or `LayoutProps`, for a `+layout.svelte` file) tells TypeScript that the type of `data` is whatever was returned from `load`:
```svelte
<!--- file: src/routes/blog/[slug]/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
</script>
```
> [!NOTE]
> The `PageProps` and `LayoutProps` types, added in 2.16.0, are a shortcut for typing the `data` prop as `PageData` or `LayoutData`, as well as other props, such as `form` for pages, or `children` for layouts. In earlier versions, you had to type these properties manually. For example, for a page:
>
> ```js
> /// file: +page.svelte
> /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
> let { data, form } = $props();
> ```
>
> Or, for a layout:
>
> ```js
> /// file: +layout.svelte
> /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
> let { data, children } = $props();
> ```
In turn, annotating the `load` function with `PageLoad`, `PageServerLoad`, `LayoutLoad` or `LayoutServerLoad` (for `+page.js`, `+page.server.js`, `+layout.js` and `+layout.server.js` respectively) ensures that `params` and the return value are correctly typed.
If you're using VS Code or any IDE that supports the language server protocol and TypeScript plugins then you can omit these types _entirely_! Svelte's IDE tooling will insert the correct types for you, so you'll get type checking without writing them yourself. It also works with our command line tool `svelte-check`.
Expand Down
29 changes: 22 additions & 7 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 @@ -25,7 +25,7 @@ export function load({ params }) {
```svelte
<!--- file: src/routes/blog/[slug]/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
</script>
Expand All @@ -34,7 +34,14 @@ export function load({ params }) {
```

> [!LEGACY]
> In Svelte 4, you'd use `export let data` instead
> Before version 2.16.0, the props of a page and layout had to be typed individually:
> ```js
> /// file: +page.svelte
> /** @type {{ data: import('./$types').PageData }} */
> let { data } = $props();
> ```
>
> In Svelte 4, you'd use `export let data` instead.
Thanks to the generated `$types` module, we get full type safety.
Expand Down Expand Up @@ -89,7 +96,7 @@ export async function load() {
```svelte
<!--- file: src/routes/blog/[slug]/+layout.svelte --->
<script>
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
/** @type {import('./$types').LayoutProps} */
let { data, children } = $props();
</script>
Expand All @@ -112,14 +119,22 @@ export async function load() {
</aside>
```

> [!LEGACY]
> `LayoutProps` was added in 2.16.0. In earlier versions, properties had to be typed individually:
> ```js
> /// file: +layout.svelte
> /** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
> let { data, children } = $props();
> ```
Data returned from layout `load` functions is available to child `+layout.svelte` components and the `+page.svelte` component as well as the layout that it 'belongs' to.
```svelte
/// file: src/routes/blog/[slug]/+page.svelte
<script>
+++import { page } from '$app/state';+++
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
+++ // we can access `data.posts` because it's returned from
Expand Down Expand Up @@ -373,7 +388,7 @@ export async function load({ parent }) {
```svelte
<!--- file: src/routes/abc/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
</script>
Expand Down Expand Up @@ -512,7 +527,7 @@ This is useful for creating skeleton loading states, for example:
```svelte
<!--- file: src/routes/blog/[slug]/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
</script>
Expand Down Expand Up @@ -653,7 +668,7 @@ export async function load({ fetch, depends }) {
<script>
import { invalidate, invalidateAll } from '$app/navigation';
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
function rerunLoadFunction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const actions = {
```svelte
<!--- file: src/routes/login/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
/** @type {import('./$types').PageProps} */
let { data, form } = $props();
</script>

Expand All @@ -153,7 +153,14 @@ export const actions = {
```
> [!LEGACY]
> In Svelte 4, you'd use `export let data` and `export let form` instead to declare properties
> `PageProps` was added in 2.16.0. In earlier versions, you had to type the `data` and `form` properties individually:
> ```js
> /// file: +page.svelte
> /** @type {{ data: import('./$types').PageData, form: import('./$types').ActionData }} */
> let { data, form } = $props();
> ```
>
> In Svelte 4, you'd use `export let data` and `export let form` instead to declare properties.
### Validation errors
Expand Down Expand Up @@ -340,7 +347,7 @@ The easiest way to progressively enhance a form is to add the `use:enhance` acti
<script>
+++import { enhance } from '$app/forms';+++

/** @type {{ form: import('./$types').ActionData }} */
/** @type {import('./$types').PageProps} */
let { form } = $props();
</script>

Expand Down Expand Up @@ -391,7 +398,7 @@ If you return a callback, you may need to reproduce part of the default `use:enh
<script>
import { enhance, +++applyAction+++ } from '$app/forms';

/** @type {{ form: import('./$types').ActionData }} */
/** @type {import('./$types').PageProps} */
let { form } = $props();
</script>

Expand Down Expand Up @@ -428,7 +435,7 @@ We can also implement progressive enhancement ourselves, without `use:enhance`,
import { invalidateAll, goto } from '$app/navigation';
import { applyAction, deserialize } from '$app/forms';

/** @type {{ form: import('./$types').ActionData }} */
/** @type {import('./$types').PageProps} */
let { form } = $props();

/** @param {SubmitEvent & { currentTarget: EventTarget & HTMLFormElement}} event */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ You might wonder how we're able to use `page.data` and other [app state]($app-st
<script>
import { setContext } from 'svelte';
/** @type {{ data: import('./$types').LayoutData }} */
/** @type {import('./$types').LayoutProps} */
let { data } = $props();
// Pass a function referencing our state
Expand Down Expand Up @@ -127,7 +127,7 @@ When you navigate around your application, SvelteKit reuses existing layout and
```svelte
<!--- file: src/routes/blog/[slug]/+page.svelte --->
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
// THIS CODE IS BUGGY!
Expand All @@ -150,7 +150,7 @@ Instead, we need to make the value [_reactive_](/tutorial/svelte/state):
```svelte
/// file: src/routes/blog/[slug]/+page.svelte
<script>
/** @type {{ data: import('./$types').PageData }} */
/** @type {import('./$types').PageProps} */
let { data } = $props();
+++ let wordCount = $derived(data.content.split(' ').length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ export async function POST({ request, platform }) {

> [!NOTE] SvelteKit's built-in `$env` module should be preferred for environment variables.
To include type declarations for your bindings, reference them in your `src/app.d.ts`:
To make these types available to your app, install `@cloudflare/workers-types` and reference them in your `src/app.d.ts`:

```ts
/// file: src/app.d.ts
import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';
+++import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';+++

declare global {
namespace App {
Expand Down Expand Up @@ -121,7 +121,7 @@ However, they will have no effect on responses dynamically rendered by SvelteKit

### Further reading

You may wish to refer to [Cloudflare's documentation for deploying a SvelteKit site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-site).
You may wish to refer to [Cloudflare's documentation for deploying a SvelteKit site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-svelte-kit-site).

### Accessing the file system

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ export async function POST({ request, platform }) {

> [!NOTE] SvelteKit's built-in `$env` module should be preferred for environment variables.
To include type declarations for your bindings, reference them in your `src/app.d.ts`:
To make these types available to your app, install `@cloudflare/workers-types` and reference them in your `src/app.d.ts`:

```ts
/// file: src/app.d.ts
import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';
+++import { KVNamespace, DurableObjectNamespace } from '@cloudflare/workers-types';+++

declare global {
namespace App {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ export default {

Vercel supports [Incremental Static Regeneration](https://vercel.com/docs/incremental-static-regeneration) (ISR), which provides the performance and cost advantages of prerendered content with the flexibility of dynamically rendered content.

> Use ISR only on routes where every visitor should see the same content (much like when you prerender). If there's anything user-specific happening (like session cookies), they should happen on the client via JavaScript only to not leak sensitive information across visits
To add ISR to a route, include the `isr` property in your `config` object:

```js
Expand All @@ -100,24 +102,44 @@ import { BYPASS_TOKEN } from '$env/static/private';

export const config = {
isr: {
// Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function.
// Setting the value to `false` means it will never expire.
expiration: 60,

// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
// with a __prerender_bypass=<token> cookie.
//
// Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.
bypassToken: BYPASS_TOKEN,

// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored,
// ensuring that they do not result in content being regenerated unnecessarily
allowQuery: ['search']
}
};
```

The `expiration` property is required; all others are optional.
> Using ISR on a route with `export const prerender = true` will have no effect, since the route is prerendered at build time
The `expiration` property is required; all others are optional. The properties are discussed in more detail below.

### expiration

The expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function. Setting the value to `false` means it will never expire. In that case, you likely want to define a bypass token to re-generate on demand.

### bypassToken

A random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset with a `__prerender_bypass=<token>` cookie.

Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.

Note that the `BYPASS_TOKEN` string must be at least 32 characters long. You could generate one using the JavaScript console like so:

```console
btoa(Math.random().toString()).substring(0,32);
```

Set this string as an environment variable on Vercel by logging in and going to your project then Settings > Environment Variables. For "Key" put `BYPASS_TOKEN` and for "value" use the string generated above, then hit "Save".

To get this key known about for local development, you can use the [Vercel CLI](https://vercel.com/docs/cli/env) by running the `vercel env pull` command locally like so:

```console
$ vercel env pull .env.development.local
```

### allowQuery

A list of valid query parameters that contribute to the cache key. Other parameters (such as utm tracking codes) will be ignored, ensuring that they do not result in content being re-generated unnecessarily. By default, query parameters are ignored.

> Pages that are [prerendered](page-options#prerender) will ignore ISR configuration.
Expand All @@ -141,7 +163,7 @@ export function load() {
```svelte
<!--- file: +layout.svelte --->
<script>
/** @type {{ data: import('./$types').LayoutServerData }} */
/** @type {import('./$types').LayoutProps} */
let { data } = $props();
</script>
Expand Down
2 changes: 2 additions & 0 deletions apps/svelte.dev/content/docs/kit/30-advanced/20-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export async function handle({ event, resolve }) {
If unimplemented, defaults to `({ event, resolve }) => resolve(event)`.

During prerendering, SvelteKit crawls your pages for links and renders each route it finds. Rendering the route invokes the `handle` function (and all other route dependencies, like `load`). If you need to exclude some code from running during this phase, check that the app is not [`building`]($app-environment#building) beforehand.

### locals

To add custom data to the request, which is passed to handlers in `+server.js` and server `load` functions, populate the `event.locals` object, as shown below.
Expand Down
Loading

0 comments on commit 78f401b

Please sign in to comment.