Skip to main content

Loading data

在渲染一个 +page.svelte 组件(及其包含的 +layout.svelte 组件)之前,我们通常需要获取一些数据。这是通过定义 load 函数来完成的。

页面数据

一个 +page.svelte 文件可以有一个兄弟 +page.js 文件,该文件导出一个 load 函数,其返回值通过 data 属性在页面中可用:

src/routes/blog/[slug]/+page
/** @type {import('./$types').PageLoad} */
export function 
function load({ params }: {
    params: any;
}): {
    post: {
        title: string;
        content: string;
    };
}
@type{import('./$types').PageLoad}
load
({ params: anyparams }) {
return {
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: `Title for ${params: anyparams.slug} goes here`, content: stringcontent: `Content for ${params: anyparams.slug} goes here` } }; }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= ({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: {
title: stringtitle: `Title for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`,
content: stringcontent: `Content for ${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.slug} goes here`
} }; };
src/routes/blog/[slug]/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

[!旧版]在 2.16.0 版本之前,页面和布局的属性必须单独输入:

+page
/** @type {{ data: import('./$types').PageData }} */
let { let data: anydata } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();
import type { import PageDataPageData } from './$types';

let { let data: PageDatadata }: { data: PageDatadata: import PageDataPageData } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

在 Svelte 4 中,您将使用 export let data 代替。

感谢生成的 $types 模块,我们获得了完全的类型安全。

一个在 load 文件中的 +page.js 函数在服务器和浏览器上都会运行(除非与 export const ssr = false 结合使用,在这种情况下它将 仅在浏览器中运行)。如果你的 load 函数应该 始终 在服务器上运行(因为使用私有环境变量,例如,或访问数据库),那么它将放在 +page.server.js 中。

一个更现实的博客文章load函数版本,该函数仅在服务器上运行并从数据库中提取数据,可能看起来像这样:

src/routes/blog/[slug]/+page.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';

export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; };

注意:类型已从 PageLoad 更改为 PageServerLoad,因为服务器 load 函数可以访问额外的参数。要了解何时使用 +page.js 和何时使用 +page.server.js,请参阅 通用与服务器

布局数据

您的 +layout.svelte 文件也可以通过 +layout.js+layout.server.js 加载数据。

src/routes/blog/[slug]/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => {
	return {
		
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };
src/routes/blog/[slug]/+layout
<script>
	/** @type {import('./$types').LayoutProps} */
	let { data, children } = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>
<script lang="ts">
	import type { LayoutProps } from './$types';

	let { data, children }: LayoutProps = $props();
</script>

<main>
	<!-- +page.svelte is `@render`ed here -->
	{@render children()}
</main>

<aside>
	<h2>More posts</h2>
	<ul>
		{#each data.posts as post}
			<li>
				<a href="/blog/{post.slug}">
					{post.title}
				</a>
			</li>
		{/each}
	</ul>
</aside>

[!旧版] LayoutProps 在 2.16.0 版本中添加。在早期版本中,属性必须单独指定类型:

+layout
/** @type {{ data: import('./$types').LayoutData, children: Snippet }} */
let { let data: anydata, let children: anychildren } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();
import type { import LayoutDataLayoutData } from './$types';

let { let data: LayoutDatadata, let children: Snippetchildren }: { data: LayoutDatadata: import LayoutDataLayoutData, children: Snippetchildren: type Snippet = /*unresolved*/ anySnippet } = 
function $props(): any
namespace $props

Declares the props that a component accepts. Example:

let { optionalProp = 42, requiredProp, bindableProp = $bindable() }: { optionalProp?: number; requiredProps: string; bindableProp: boolean } = $props();

https://svelte.dev/docs/svelte/$props

$props
();

数据从 load 函数返回,可供子 +layout.svelte 组件以及 +page.svelte 组件以及它所属的布局使用。

src/routes/blog/[slug]/+page
<script>
	import { page } from '$app/state';

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

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}
<script lang="ts">
	import { page } from '$app/state';
	import type { PageProps } from './$types';
	let { data }: PageProps = $props();

	// we can access `data.posts` because it's returned from
	// the parent layout `load` function
	let index = $derived(data.posts.findIndex(post => post.slug === page.params.slug));
	let next = $derived(data.posts[index + 1]);
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#if next}
	<p>Next post: <a href="/blog/{next.slug}">{next.title}</a></p>
{/if}

[注意] 如果多个 load 函数返回具有相同键的数据,则最后一个“获胜”——一个布局 load 返回 { a: 1, b: 2 } 和一个页面 load 返回 { b: 3, c: 4 } 的结果将是 { a: 1, b: 3, c: 4 }

页面数据

组件 +page.svelte 以及其上方的每个 +layout.svelte 组件,都可以访问自己的数据以及其父级的所有数据。

在某些情况下,我们可能需要相反的情况——父布局可能需要访问页面数据或子布局的数据。例如,根布局可能希望访问从+page.js+page.server.js中的load函数返回的title属性。这可以通过page.data来实现:

src/routes/+layout
<script>
	import { page } from '$app/state';
</script>

<svelte:head>
	<title>{page.data.title}</title>
</svelte:head>
<script lang="ts">
	import { page } from '$app/state';
</script>

<svelte:head>
	<title>{page.data.title}</title>
</svelte:head>

类型信息由 page.data 提供,由 App.PageData 提供。

[!旧版] $app/state 在 SvelteKit 2.12 中被添加。如果您使用的是更早的版本或使用 Svelte 4,请使用 $app/stores 代替。它提供了一个具有相同接口的 page 存储,您可以订阅它,例如 $page.data.title

通用与服务器

我们已看到,有两种类型的 load 函数:

  • +page.js+layout.js 文件导出 通用加载 函数,这些函数在服务器和浏览器上都能运行
  • +page.server.js+layout.server.js 文件导出 serverload 函数,这些函数仅在服务器端运行

概念上,它们是同一件事,但有一些重要的差异需要注意。

何时运行哪个加载函数?

服务器 加载 函数 总是 在服务器上运行。

默认情况下,通用 加载 函数在 SSR(服务器端渲染)期间用户首次访问您的页面时在服务器上运行。然后它们将在 hydration 期间再次运行,重用来自 fetch 请求 的任何响应。所有后续的通用 加载 函数调用都发生在浏览器中。您可以通过 页面选项 定制行为。如果您禁用 服务器端渲染,您将获得一个 SPA,并且通用 加载 函数 始终 在客户端运行。

如果路由同时包含通用和服务器 加载 函数,则服务器 加载 先运行。

A 加载函数在运行时被调用,除非您预渲染页面——在这种情况下,它在构建时被调用。

输入

两者都通用的和服务器 load 函数可以访问描述请求的属性(paramsrouteurl)以及各种函数(fetchsetHeadersparentdependsuntrack)。这些内容在以下章节中描述。

服务器 load 函数通过一个 ServerLoadEvent 被调用,该事件继承自 clientAddresscookieslocalsplatformrequest,它们都来自 RequestEvent

通用load函数使用LoadEvent调用,该事件具有data属性。如果您在+page.js+page.server.js(或+layout.js+layout.server.js)中都有load函数,则服务器load函数的返回值是通用load函数参数的data属性。

Input: Output:

一个通用的load函数可以返回一个包含任何值的对象,包括像自定义类和组件构造函数这样的东西。

服务器 加载 函数必须返回可以与 反序列化 一并序列化的数据——任何可以表示为 JSON 的内容以及类似 BigIntDateMapSetRegExp 的内容,或者重复/循环引用——以便通过网络传输。如果您的数据包含 承诺,则将流式传输到浏览器。如果您需要序列化/反序列化自定义类型,请使用 传输钩子

何时使用哪个

服务器 加载 函数在您需要直接从数据库或文件系统访问数据或需要使用私有环境变量时很方便。

通用 加载 函数在您需要从外部 API 获取 数据且不需要私有凭证时很有用,因为 SvelteKit 可以直接从 API 获取数据,而不是通过您的服务器。当您需要返回无法序列化的内容时,例如 Svelte 组件构造函数,它们也非常有用。

在罕见情况下,您可能需要同时使用两者——例如,您可能需要返回一个使用从您的服务器加载数据初始化的自定义类的实例。当同时使用时,服务器的 load 返回值不是直接传递给页面,而是传递给通用的 load 函数(作为 data 属性):

src/routes/+page.server
/** @type {import('./$types').PageServerLoad} */
export async function 
function load(): Promise<{
    serverMessage: string;
}>
@type{import('./$types').PageServerLoad}
load
() {
return { serverMessage: stringserverMessage: 'hello from server load function' }; }
import type { 
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
} from './$types';
export const const load: PageServerLoadload:
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
= async () => {
return { serverMessage: stringserverMessage: 'hello from server load function' }; };
src/routes/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ data }: {
    data: any;
}): Promise<{
    serverMessage: any;
    universalMessage: string;
}>
@type{import('./$types').PageLoad}
load
({ data: anydata }) {
return { serverMessage: anyserverMessage: data: anydata.serverMessage, universalMessage: stringuniversalMessage: 'hello from universal load function' }; }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({ data: Record<string, any> | null

Contains the data returned by the route’s server load function (in +layout.server.js or +page.server.js), if any.

data
}) => {
return { serverMessage: anyserverMessage: data: Record<string, any> | null

Contains the data returned by the route’s server load function (in +layout.server.js or +page.server.js), if any.

data
.serverMessage,
universalMessage: stringuniversalMessage: 'hello from universal load function' }; };

使用 URL 数据

通常,load 函数以某种方式依赖于 URL。为此,load 函数为您提供了 urlrouteparams

url

一个包含如originhostnamepathnamesearchParams(其中包含解析后的查询字符串作为URLSearchParams对象)等属性的URL实例。在load期间无法访问url.hash,因为在服务器上不可用。

[注意] 在某些环境中,这是在服务器端渲染期间从请求头中派生出来的。如果您使用adapter-node,例如,您可能需要配置适配器,以便 URL 正确。

路由

包含当前路由目录名称,相对于 src/routes

src/routes/a/[b]/[...c]/+page
/** @type {import('./$types').PageLoad} */
export function 
function load({ route }: {
    route: any;
}): void
@type{import('./$types').PageLoad}
load
({ route: anyroute }) {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object’s methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100
log
(route: anyroute.id); // '/a/[b]/[...c]'
}
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= ({
route: {
    id: string | null;
}

Info about the current route

route
}) => {
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object’s methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100
log
(
route: {
    id: string | null;
}

Info about the current route

route
.id: string | null

The ID of the current route - e.g. for src/routes/blog/[slug], it would be /blog/[slug]. It is null when no route is matched.

id
); // '/a/[b]/[...c]'
};

params

paramsurl.pathnameroute.id 派生。

给定一个 route.id/a/[b]/[...c] 和一个 url.pathname/a/x/y/zparams 对象将如下所示:

{ "b": "x" c: y/z }

制作获取请求

要从外部 API 或一个+server.js处理器获取数据,您可以使用提供的fetch函数,该函数的行为与原生的fetch网络 API相同,并增加了几个额外功能:

  • 它可以用来在服务器上发起认证请求,因为它继承了页面请求的cookieauthorization头部。
  • 它可以对服务器进行相对请求(通常情况下,在服务器环境中使用 fetch 需要一个带有源头的 URL)。
  • 内部请求(例如对 +server.js 路由的请求)在服务器上运行时直接发送到处理函数,无需 HTTP 调用的开销。
  • 在服务器端渲染过程中,响应将被捕获并内联到渲染的 HTML 中,通过挂钩到textjsonarrayBuffer方法以及Response对象。请注意,除非明确通过 filterSerializedResponseHeaders 包含,否则头部信息将不会被序列化。
  • 在加水过程中,响应将从 HTML 中读取,确保一致性并防止额外的网络请求 - 如果您在使用浏览器时在控制台收到警告,使用的是fetch而不是load``fetch,这就是原因。
src/routes/items/[id]/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, params }: {
    fetch: any;
    params: any;
}): Promise<{
    item: any;
}>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, params: anyparams }) {
const const res: anyres = await fetch: anyfetch(`/api/items/${params: anyparams.id}`); const const item: anyitem = await const res: anyres.json(); return { item: anyitem }; }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
}) => {
const const res: Responseres = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(`/api/items/${params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
.id}`);
const const item: anyitem = await const res: Responseres.Body.json(): Promise<any>json(); return { item: anyitem }; };

Cookies

服务器 加载 函数可以获取和设置 cookies

src/routes/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async ({ cookies: Cookies

Get or set cookies related to the current request

cookies
}) => {
const const sessionid: string | undefinedsessionid = cookies: Cookies

Get or set cookies related to the current request

cookies
.Cookies.get: (name: string, opts?: CookieParseOptions) => string | undefined

Gets a cookie that was previously set with cookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly to cookie.parse. See documentation here
get
('sessionid');
return {
user: {
    name: string;
    avatar: string;
}
user
: await module "$lib/server/database"db.
function getUser(sessionid: string | undefined): Promise<{
    name: string;
    avatar: string;
}>
getUser
(const sessionid: string | undefinedsessionid)
}; };

Cookies 仅当目标主机与 SvelteKit 应用程序或其更具体的子域名相同时,才会通过提供的 fetch 函数传递。

例如,如果 SvelteKit 正在为 my.domain.com 提供服务:

  • domain.com 不会接收 cookies
  • my.domain.com 将会接收 cookies
  • api.domain.com 不会接收 cookies
  • sub.my.domain.com 将会接收 cookies

其他 cookie 在设置credentials: 'include'时不会被传递,因为 SvelteKit 不知道哪个 cookie 属于哪个域名(浏览器不会传递这些信息),因此转发任何这些 cookie 都不安全。使用handleFetch 钩子来解决这个问题。

头信息

服务器和通用 load 函数都可以访问一个 setHeaders 函数,当在服务器上运行时,可以设置响应的头部信息。(在浏览器中运行时,setHeaders 无效。)如果您想使页面被缓存,这很有用,例如:

src/routes/products/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, setHeaders }: {
    fetch: any;
    setHeaders: any;
}): Promise<any>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, setHeaders: anysetHeaders }) {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: anyresponse = await fetch: anyfetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: anysetHeaders({ age: anyage: const response: anyresponse.headers.get('age'), 'cache-control': const response: anyresponse.headers.get('cache-control') }); return const response: anyresponse.json(); }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

src/routes/blog/+page
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
}) => {
const const url: "https://cms.example.com/products.json"url = `https://cms.example.com/products.json`; const const response: Responseresponse = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch(const url: "https://cms.example.com/products.json"url); // Headers are only set during SSR, caching the page's HTML // for the same length of time as the underlying data. setHeaders: (headers: Record<string, string>) => void

If you need to set headers for the response, you can do so using the this method. This is useful if you want the page to be cached, for example:

src/routes/blog/+page
export async function load({ fetch, setHeaders }) {
	const url = `https://cms.example.com/articles.json`;
	const response = await fetch(url);

	setHeaders({
		age: response.headers.get('age'),
		'cache-control': response.headers.get('cache-control')
	});

	return response.json();
}

Setting the same header multiple times (even in separate load functions) is an error — you can only set a given header once.

You cannot add a set-cookie header with setHeaders — use the cookies API in a server-only load function instead.

setHeaders has no effect when a load function runs in the browser.

setHeaders
({
age: string | nullage: const response: Responseresponse.Response.headers: Headersheaders.Headers.get(name: string): string | nullget('age'), 'cache-control': const response: Responseresponse.Response.headers: Headersheaders.Headers.get(name: string): string | nullget('cache-control') }); return const response: Responseresponse.Body.json(): Promise<any>json(); };

设置相同的标题多次(即使在单独的 load 函数中)是错误的。您只能使用 setHeaders 函数设置给定的标题一次。您不能使用 setHeaders 添加 set-cookie 标题 — 请使用 cookies.set(name, value, options) 代替。

使用父数据

偶尔,对于 加载 函数来说,访问父 加载 函数中的数据是有用的,这可以通过 await parent() 实现:

src/routes/+layout
/** @type {import('./$types').LayoutLoad} */
export function 
function load(): {
    a: number;
}
@type{import('./$types').LayoutLoad}
load
() {
return { a: numbera: 1 }; }
import type { 
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
} from './$types';
export const const load: LayoutLoadload:
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
= () => {
return { a: numbera: 1 }; };
src/routes/abc/+layout
/** @type {import('./$types').LayoutLoad} */
export async function 
function load({ parent }: {
    parent: any;
}): Promise<{
    b: any;
}>
@type{import('./$types').LayoutLoad}
load
({ parent: anyparent }) {
const { const a: anya } = await parent: anyparent(); return { b: anyb: const a: anya + 1 }; }
import type { 
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
} from './$types';
export const const load: LayoutLoadload:
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type LayoutLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
LayoutLoad
= async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anya } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { b: anyb: const a: anya + 1 }; };
src/routes/abc/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ parent }: {
    parent: any;
}): Promise<{
    c: any;
}>
@type{import('./$types').PageLoad}
load
({ parent: anyparent }) {
const { const a: anya, const b: anyb } = await parent: anyparent(); return { c: anyc: const a: anya + const b: anyb }; }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({ parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const { const a: anya, const b: anyb } = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { c: anyc: const a: anya + const b: anyb }; };
src/routes/abc/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<!-- renders `1 + 2 = 3` -->
<p>{data.a} + {data.b} = {data.c}</p>

[!注意] 注意到 load 函数在 +page.js 中接收来自布局 load 函数的合并数据,而不仅仅是直接父级。

+page.server.js+layout.server.js内部,parent从父+layout.server.js文件中返回数据。

+page.js+layout.js中,它将返回父+layout.js文件中的数据。然而,缺失的+layout.js被视为一个({ data }) => data函数,这意味着它也将返回父+layout.server.js文件中的数据,这些数据不会被+layout.js文件“覆盖”。

请注意在使用await parent()时不要引入瀑布效应。例如,这里getData(params)不依赖于调用parent()的结果,因此我们应该先调用它,以避免延迟渲染。

+page
/** @type {import('./$types').PageLoad} */
export async function function load(event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageLoad}
load
({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
, parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) {
const parentData = await parent(); const
const data: {
    meta: any;
}
data
= await
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
);
const const parentData: Record<string, any>parentData = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { ...
const data: {
    meta: any;
}
data
,
meta: anymeta: { ...const parentData: Record<string, any>parentData.meta, ...
const data: {
    meta: any;
}
data
.meta: anymeta }
}; }
import type { type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad } from './$types';

export const const load: PageLoadload: type PageLoad = (event: LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageLoad = async ({ params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
, parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
}) => {
const parentData = await parent(); const
const data: {
    meta: any;
}
data
= await
function getData(params: Record<string, string>): Promise<{
    meta: any;
}>
getData
(params: Record<string, any>

The parameters of the current page - e.g. for a route like /blog/[slug], a { slug: string } object

params
);
const const parentData: Record<string, any>parentData = await parent: () => Promise<Record<string, any>>

await parent() returns data from parent +layout.js load functions. Implicitly, a missing +layout.js is treated as a ({ data }) => data function, meaning that it will return and forward data from parent +layout.server.js files.

Be careful not to introduce accidental waterfalls when using await parent(). If for example you only want to merge parent data into the returned output, call it after fetching your other data.

parent
();
return { ...
const data: {
    meta: any;
}
data
,
meta: anymeta: { ...const parentData: Record<string, any>parentData.meta, ...
const data: {
    meta: any;
}
data
.meta: anymeta }
}; };

错误

如果在 加载 过程中抛出错误,则将渲染最近的 +error.svelte。对于 预期 错误,请使用来自 @sveltejs/kiterror 辅助函数来指定 HTTP 状态码和可选消息:

src/routes/admin/+layout.server
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(403, 'not an admin');
} }
import { function error(status: number, body: App.Error): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
} from '@sveltejs/kit';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
} | undefined
user
) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(401, 'not logged in');
} if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
    isAdmin: boolean;
}
user
.isAdmin: booleanisAdmin) {
function error(status: number, body?: {
    message: string;
} extends App.Error ? App.Error | string | undefined : never): never (+1 overload)

Throws an error with a HTTP status code and an optional message. When called during request handling, this will cause SvelteKit to return an error response without invoking handleError. Make sure you’re not catching the thrown error, which would prevent SvelteKit from handling it.

@paramstatus The HTTP status code. Must be in the range 400-599.
@parambody An object that conforms to the App.Error type. If a string is passed, it will be used as the message property.
@throwsHttpError This error instructs SvelteKit to initiate HTTP error handling.
@throwsError If the provided status is invalid (not between 400 and 599).
error
(403, 'not an admin');
} };

调用 error(...) 将会抛出异常,这使得在辅助函数内部停止执行变得容易。

如果抛出意外错误,SvelteKit 将调用handleError并将其视为 500 内部错误。

[!注意] 在 SvelteKit 1.x 中您必须 手动抛出 错误

重定向

要重定向用户,请使用来自 @sveltejs/kitredirect 辅助函数来指定应重定向到的位置,并附带一个 3xx 状态码。类似于调用 error(...),调用 redirect(...) 将会抛出异常,这使得在辅助函数内部停止执行变得容易。

src/routes/user/+layout.server
import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
/** @type {import('./$types').LayoutServerLoad} */ export function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(307, '/login');
} }
import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types'; export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = ({ locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
}) => {
if (!locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.
App.Locals.user?: {
    name: string;
} | undefined
user
) {
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(307, '/login');
} };

[注意] 不要在 try {...} 块内使用 redirect(),因为重定向将立即触发 catch 语句。

在浏览器中,您还可以使用 $app.navigation 中的 gotoload 函数外进行程序化导航。

[!注意] 在 SvelteKit 1.x 中您必须自己 抛出 重定向

流式传输与承诺

当使用服务器 加载 时,一旦解决,承诺将被流式传输到浏览器。如果您有缓慢的非关键数据,这很有用,因为您可以在所有数据可用之前开始渲染页面:

src/routes/blog/[slug]/+page.server
/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) {
return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post
comments: Promise<{
    content: string;
}>
comments
:
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug),
post: {
    title: string;
    content: string;
}
post
: await
const loadPost: (slug: string) => Promise<{
    title: string;
    content: string;
}>
loadPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; }
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';

export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) => {
return { // make sure the `await` happens at the end, otherwise we // can't start loading comments until we've loaded the post
comments: Promise<{
    content: string;
}>
comments
:
const loadComments: (slug: string) => Promise<{
    content: string;
}>
loadComments
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug),
post: {
    title: string;
    content: string;
}
post
: await
const loadPost: (slug: string) => Promise<{
    title: string;
    content: string;
}>
loadPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; };

这对于创建骨架加载状态很有用,例如:

src/routes/blog/[slug]/+page
<script>
	/** @type {import('./$types').PageProps} */
	let { data } = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}
<script lang="ts">
	import type { PageProps } from './$types';

	let { data }: PageProps = $props();
</script>

<h1>{data.post.title}</h1>
<div>{@html data.post.content}</div>

{#await data.comments}
	Loading comments...
{:then comments}
	{#each comments as comment}
		<p>{comment.content}</p>
	{/each}
{:catch error}
	<p>error loading comments: {error.message}</p>
{/await}

在流式传输数据时,请小心正确处理承诺拒绝。更具体地说,如果延迟加载的承诺在渲染开始之前失败(此时会被捕获)并且没有以某种方式处理错误,服务器可能会因为“未处理的承诺拒绝”错误而崩溃。当在load函数中直接使用 SvelteKit 的fetch时,SvelteKit 会为你处理这种情况。对于其他承诺,只需将一个 noop-catch附加到承诺上,即可将其标记为已处理。

src/routes/+page.server
/** @type {import('./$types').PageServerLoad} */
export function 
function load({ fetch }: {
    fetch: any;
}): {
    ok_manual: Promise<never>;
    ok_fetch: any;
    dangerous_unhandled: Promise<never>;
}
@type{import('./$types').PageServerLoad}
load
({ fetch: anyfetch }) {
const const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual, ok_fetch: anyok_fetch: fetch: anyfetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
()
}; }
import type { 
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
} from './$types';
export const const load: PageServerLoadload:
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageServerLoad = (event: Kit.ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageServerLoad
= ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here.

fetch
}) => {
const const ok_manual: Promise<never>ok_manual = var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
();
const ok_manual: Promise<never>ok_manual.Promise<never>.catch<void>(onrejected?: ((reason: any) => void | PromiseLike<void>) | null | undefined): Promise<void>

Attaches a callback for only the rejection of the Promise.

@paramonrejected The callback to execute when the Promise is rejected.
@returnsA Promise for the completion of the callback.
catch
(() => {});
return { ok_manual: Promise<never>ok_manual, ok_fetch: Promise<Response>ok_fetch: fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('/fetch/that/could/fail'), dangerous_unhandled: Promise<never>dangerous_unhandled: var Promise: PromiseConstructor

Represents the completion of an asynchronous operation

Promise
.PromiseConstructor.reject<never>(reason?: any): Promise<never>

Creates a new rejected promise for the provided reason.

@paramreason The reason the promise was rejected.
@returnsA new rejected Promise.
reject
()
}; };

[注意] 在不支持流式传输的平台,例如 AWS Lambda 或 Firebase 上,响应将被缓冲。这意味着页面将仅在所有承诺解决后才会渲染。如果您正在使用代理(例如 NGINX),请确保它不会缓冲代理服务器的响应。

[注意] 仅当启用 JavaScript 时,流式数据才会工作。如果页面是服务器渲染的,应避免从通用的load函数返回承诺,因为这些不是流式的——相反,当函数在浏览器中重新运行时,承诺将被重新创建。

[!注意] 响应一旦开始流式传输,其头部和状态码就不能更改,因此您不能在流式承诺中 设置头部 或抛出重定向。

[!注意] 在 SvelteKit 1.x 中顶级承诺自动等待,只有嵌套承诺被流式传输。

并行加载

当渲染(或导航到)页面时,SvelteKit 会并发运行所有load函数,避免请求瀑布效应。在客户端导航期间,调用多个服务器load函数的结果被组合成一个单一响应。一旦所有load函数返回,页面就会被渲染。

重新运行加载函数

SvelteKit 跟踪每个 load 函数的依赖关系,以避免在导航过程中不必要地重新运行它。

例如,给定一对 load 函数,如下所示...

src/routes/blog/[slug]/+page.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').PageServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').PageServerLoad}
load
({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad } from './$types';

export const const load: PageServerLoadload: type PageServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>PageServerLoad = async ({ params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
}) => {
return {
post: {
    title: string;
    content: string;
}
post
: await module "$lib/server/database"db.
function getPost(slug: string): Promise<{
    title: string;
    content: string;
}>
getPost
(params: Record<string, any>

The parameters of the current route - e.g. for a route like /blog/[slug], a { slug: string } object.

params
.slug)
}; };
src/routes/blog/[slug]/+layout.server
import * as module "$lib/server/database"db from '$lib/server/database';

/** @type {import('./$types').LayoutServerLoad} */
export async function function load(event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>): MaybePromise<void | Record<string, any>>
@type{import('./$types').LayoutServerLoad}
load
() {
return {
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; }
import * as module "$lib/server/database"db from '$lib/server/database';
import type { type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad } from './$types';

export const const load: LayoutServerLoadload: type LayoutServerLoad = (event: ServerLoadEvent<Record<string, any>, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>LayoutServerLoad = async () => {
	return {
		
posts: {
    title: string;
    slug: string;
}[]
posts
: await module "$lib/server/database"db.
function getPostSummaries(): Promise<Array<{
    title: string;
    slug: string;
}>>
getPostSummaries
()
}; };

...在+page.server.js中的代码将在我们从 /blog/trying-the-raw-meat-diet 导航到/blog/i-regret-my-choices时重新运行,因为params.slug已更改。在+layout.server.js中的代码不会,因为数据仍然有效。换句话说,我们不会再次调用db.getPostSummaries()

一个调用 load 函数的 await parent() 也会在父 load 函数重新运行时重新运行。

依赖跟踪在 加载 函数返回后不适用 —— 例如,在嵌套的 承诺 中访问 params.x 不会导致函数重新运行,当 params.x 发生变化时。 (别担心,如果你不小心这样做,开发过程中你会收到警告。) 相反,请在你的 load 函数的主体中访问该参数。

搜索参数独立于 URL 的其余部分进行跟踪。例如,在load函数内部访问 event.url.searchParams.get("x") 将使该load函数在从?x=1导航到?x=2时重新运行,但不会在从?x=1&y=1导航到?x=1&y=2时重新运行。

取消跟踪依赖

在罕见情况下,您可能希望从依赖跟踪机制中排除某些内容。您可以使用提供的 untrack 函数来完成此操作:

src/routes/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ untrack, url }: {
    untrack: any;
    url: any;
}): Promise<{
    message: string;
} | undefined>
@type{import('./$types').PageLoad}
load
({ untrack: anyuntrack, url: anyurl }) {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: anyuntrack(() => url: anyurl.pathname === '/')) { return { message: stringmessage: 'Welcome!' }; } }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({ untrack: <T>(fn: () => T) => T

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

src/routes/+page.server
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
, url: URL

The URL of the current page

url
}) => {
// Untrack url.pathname so that path changes don't trigger a rerun if (untrack: <boolean>(fn: () => boolean) => boolean

Use this function to opt out of dependency tracking for everything that is synchronously called within the callback. Example:

src/routes/+page.server
export async function load({ untrack, url }) {
	// Untrack url.pathname so that path changes don't trigger a rerun
	if (untrack(() => url.pathname === '/')) {
		return { message: 'Welcome!' };
	}
}
untrack
(() => url: URL

The URL of the current page

url
.URL.pathname: stringpathname === '/')) {
return { message: stringmessage: 'Welcome!' }; } };

手动失效

您也可以使用load函数重新运行适用于当前页面的功能,通过invalidate(url),这将重新运行所有依赖于urlload函数,以及invalidateAll(),这将重新运行每个load函数。服务器负载函数永远不会自动依赖于获取的url,以避免将秘密泄露给客户端。

一个 load 函数在调用 url 时依赖于它,如果它调用了 fetch(url)depends(url)。请注意,url 可以是一个以 [a-z]: 开头的自定义标识符。

src/routes/random-number/+page
/** @type {import('./$types').PageLoad} */
export async function 
function load({ fetch, depends }: {
    fetch: any;
    depends: any;
}): Promise<{
    number: any;
}>
@type{import('./$types').PageLoad}
load
({ fetch: anyfetch, depends: anydepends }) {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: anyresponse = await fetch: anyfetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: anydepends('app:random'); return { number: anynumber: await const response: anyresponse.json() }; }
import type { 
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
} from './$types';
export const const load: PageLoadload:
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
type PageLoad = (event: Kit.LoadEvent<Record<string, any>, Record<string, any> | null, Record<string, any>, string | null>) => MaybePromise<void | Record<string, any>>
PageLoad
= async ({
fetch: {
    (input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
    (input: string | URL | globalThis.Request, init?: RequestInit): Promise<Response>;
}

fetch is equivalent to the native fetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits the cookie and authorization headers for the page request.
  • It can make relative requests on the server (ordinarily, fetch requires a URL with an origin when used in a server context).
  • Internal requests (e.g. for +server.js routes) go directly to the handler function when running on the server, without the overhead of an HTTP call.
  • During server-side rendering, the response will be captured and inlined into the rendered HTML by hooking into the text and json methods of the Response object. Note that headers will not be serialized, unless explicitly included via filterSerializedResponseHeaders
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request.

You can learn more about making credentialed requests with cookies here

fetch
, depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won’t need this, as fetch calls depends on your behalf — it’s only necessary if you’re using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

src/routes/+page
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
src/routes/+page
&#x3C;script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
&#x3C;/script>

&#x3C;p>{data.count}&#x3C;p>
&#x3C;button on:click={increase}>Increase Count&#x3C;/button>
depends
}) => {
// load reruns when `invalidate('https://api.example.com/random-number')` is called... const const response: Responseresponse = await fetch: (input: string | URL | globalThis.Request, init?: RequestInit) => Promise<Response> (+1 overload)fetch('https://api.example.com/random-number'); // ...or when `invalidate('app:random')` is called depends: (...deps: Array<`${string}:${string}`>) => void

This function declares that the load function has a dependency on one or more URLs or custom identifiers, which can subsequently be used with invalidate() to cause load to rerun.

Most of the time you won’t need this, as fetch calls depends on your behalf — it’s only necessary if you’re using a custom API client that bypasses fetch.

URLs can be absolute or relative to the page being loaded, and must be encoded.

Custom identifiers have to be prefixed with one or more lowercase letters followed by a colon to conform to the URI specification.

The following example shows how to use depends to register a dependency on a custom identifier, which is invalidated after a button click, making the load function rerun.

src/routes/+page
let count = 0;
export async function load({ depends }) {
	depends('increase:count');

	return { count: count++ };
}
src/routes/+page
&#x3C;script>
	import { invalidate } from '$app/navigation';

	let { data } = $props();

	const increase = async () => {
		await invalidate('increase:count');
	}
&#x3C;/script>

&#x3C;p>{data.count}&#x3C;p>
&#x3C;button on:click={increase}>Increase Count&#x3C;/button>
depends
('app:random');
return { number: anynumber: await const response: Responseresponse.Body.json(): Promise<any>json() }; };
src/routes/random-number/+page
<script>
	import { invalidate, invalidateAll } from '$app/navigation';

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

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>
<script lang="ts">
	import { invalidate, invalidateAll } from '$app/navigation';
	import type { PageProps } from './$types';
	let { data }: PageProps = $props();

	function rerunLoadFunction() {
		// any of these will cause the `load` function to rerun
		invalidate('app:random');
		invalidate('https://api.example.com/random-number');
		invalidate(url => url.href.includes('random-number'));
		invalidateAll();
	}
</script>

<p>random number: {data.number}</p>
<button onclick={rerunLoadFunction}>Update random number</button>

何时重新运行加载函数?

总结来说,以下情况下将重新运行 load 函数:

  • 它引用了params属性的一个值已更改的属性
  • 它引用了一个属性 url(例如 url.pathnameurl.search),其值已更改。在 request.url 中的属性 被跟踪
  • 它调用 url.searchParams.get(...)url.searchParams.getAll(...)url.searchParams.has(...) 并更改相关参数。访问 url.searchParams 的其他属性将产生与访问 url.search 相同的效果。
  • 它调用 await parent() 和一个父 load 函数重新运行
  • 一个子 load 函数调用 await parent() 并正在重新运行,而父函数是一个服务器负载函数
  • 它通过fetch(仅限通用加载)或depends声明了对特定 URL 的依赖,并且该 URL 被invalidate(url)标记为无效
  • 所有活动 load 函数均被强制重新运行,使用 invalidateAll()

paramsurl 可以根据 <a href=".."> 链接点击、<form> 交互goto 调用或 redirect 重定向进行更改。

请注意,重新运行一个 load 函数将更新对应于 +layout.svelte+page.sveltedata 属性;它不会导致组件被重新创建。因此,内部状态得以保留。如果这不是您想要的结果,您可以在 afterNavigate 回调中重置您需要重置的任何内容,或者将您的组件包裹在一个 {#key ...} 块中。

认证的影响

一些数据加载功能对身份验证检查具有重要意义:

  • 布局 加载 函数不在每个请求上运行,例如在客户端导航子路由之间时。 (加载函数何时重新运行?)
  • 布局和页面 加载 函数并发运行,除非调用 await parent()。如果布局 加载 抛出异常,则页面 加载 函数运行,但客户端将不会接收到返回的数据。

有几种可能的策略来确保在受保护的代码之前进行身份验证检查。

为防止数据瀑布并保留布局 load 缓存:

  • 使用钩子在所有加载函数运行之前保护多个路由
  • 直接在 +page.server.js``load 函数中使用 auth guards 进行路由特定保护

+layout.server.js 中添加身份验证守卫要求所有子页面在受保护代码之前调用 await parent()。除非每个子页面都依赖于从 await parent() 返回的数据,否则其他选项将具有更高的性能。

使用 getRequestEvent

当运行服务器 load 函数时,作为函数参数传递的 event 对象也可以通过 getRequestEvent 获取。这允许共享逻辑(如身份验证守卫)在不需要传递的情况下访问当前请求的信息。

例如,您可能有一个需要用户登录的功能,如果未登录,则重定向到 /login

src/lib/server/auth
import { function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
} from '@sveltejs/kit';
import { function getRequestEvent(): RequestEvent<Partial<Record<string, string>>, string | null>

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
getRequestEvent
} from '$app/server';
export function function requireLogin(): UserrequireLogin() { const { const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
, const url: URL

The requested URL.

url
} = function getRequestEvent(): RequestEvent<Partial<Record<string, string>>, string | null>

Returns the current RequestEvent. Can be used inside server hooks, server load functions, actions, and endpoints (and functions called by them).

In environments without AsyncLocalStorage, this must be called synchronously (i.e. not after an await).

@since2.20.0
getRequestEvent
();
// assume `locals.user` is populated in `handle` if (!const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.App.Locals.user?: User | undefineduser) {
const const redirectTo: stringredirectTo = const url: URL

The requested URL.

url
.URL.pathname: stringpathname + const url: URL

The requested URL.

url
.URL.search: stringsearch;
const const params: URLSearchParamsparams = new var URLSearchParams: new (init?: string[][] | Record<string, string> | string | URLSearchParams) => URLSearchParams

MDN Reference

URLSearchParams class is a global reference for import { URLSearchParams } from 'node:url' https://nodejs.org/api/url.html#class-urlsearchparams

@sincev10.0.0
URLSearchParams
({ redirectTo: stringredirectTo });
function redirect(status: 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | ({} & number), location: string | URL): never

Redirect a request. When called during request handling, SvelteKit will return a redirect response. Make sure you’re not catching the thrown redirect, which would prevent SvelteKit from handling it.

Most common status codes:

  • 303 See Other: redirect as a GET request (often used after a form POST request)
  • 307 Temporary Redirect: redirect will keep the request method
  • 308 Permanent Redirect: redirect will keep the request method, SEO will be transferred to the new page

See all redirect status codes

@paramstatus The HTTP status code. Must be in the range 300-308.
@paramlocation The location to redirect to.
@throwsRedirect This error instructs SvelteKit to redirect to the specified location.
@throwsError If the provided status is invalid.
redirect
(307, `/login?${const params: URLSearchParamsparams}`);
} return const locals: App.Locals

Contains custom data that was added to the request within the server handle hook.

locals
.App.Locals.user?: Useruser;
}

现在,您可以在任何load函数(或例如表单操作)中调用requireLogin,以确保用户已登录:

+page.server
import { function requireLogin(): UserrequireLogin } from '$lib/server/auth';

export function 
function load(): {
    message: string;
}
load
() {
const const user: Useruser = function requireLogin(): UserrequireLogin(); // `user` is guaranteed to be a user object here, because otherwise // `requireLogin` would throw a redirect and we wouldn't get here return { message: stringmessage: `hello ${const user: Useruser.User.name: stringname}!` }; }

进一步阅读

Edit this page on GitHub llms.txt

previous next