Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
SvelteKitCore concepts

Loading data

Before a+page.svelte component (and its containing+layout.svelte components) can be rendered, we often need to get some data. This is done by definingload functions.

Page data

A+page.svelte file can have a sibling+page.js that exports aload function, the return value of which is available to the page via thedata prop:

src/routes/blog/[slug]/+page
/**@type{import('./$types').PageLoad}*/exportfunction
functionload({ 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`}};}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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>{@htmldata.post.content}</div>
<scriptlang="ts">importtype{ PageProps }from'./$types';let{ data }:PageProps=$props();</script><h1>{data.post.title}</h1><div>{@htmldata.post.content}</div>
Legacy mode

Before version 2.16.0, the props of a page and layout had to be typed individually:

+page
/**@type{{ data: import('./$types').PageData }}*/let{letdata:anydata}=
function$props():anynamespace$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
();
importtype{importPageDataPageData}from'./$types';let{letdata:PageDatadata}:{data:PageDatadata:importPageDataPageData}=
function$props():anynamespace$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
();

In Svelte 4, you’d useexport let data instead.

Thanks to the generated$types module, we get full type safety.

Aload function in a+page.js file runs both on the server and in the browser (unless combined withexport const ssr = false, in which case it willonly run in the browser). If yourload function shouldalways run on the server (because it uses private environment variables, for example, or accesses a database) then it would go in a+page.server.js instead.

A more realistic version of your blog post’sload function, that only runs on the server and pulls data from a database, might look like this:

src/routes/blog/[slug]/+page.server
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';/**@type{import('./$types').PageServerLoad}*/exportasyncfunctionfunctionload(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
:awaitmodule"$lib/server/database"db.
functiongetPost(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*asmodule"$lib/server/database"dbfrom'$lib/server/database';importtype{typePageServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageServerLoad}from'./$types';exportconstconstload:PageServerLoadload:typePageServerLoad=(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
:awaitmodule"$lib/server/database"db.
functiongetPost(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)
};};

Notice that the type changed fromPageLoad toPageServerLoad, because serverload functions can access additional arguments. To understand when to use+page.js and when to use+page.server.js, seeUniversal vs server.

Layout data

Your+layout.svelte files can also load data, via+layout.js or+layout.server.js.

src/routes/blog/[slug]/+layout.server
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';/**@type{import('./$types').LayoutServerLoad}*/exportasyncfunctionfunctionload(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
:awaitmodule"$lib/server/database"db.
functiongetPostSummaries():Promise<Array<{title:string;slug:string;}>>
getPostSummaries
()
};}
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';importtype{typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad}from'./$types';exportconstconstload:LayoutServerLoadload:typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad=async()=>{return{
posts:{title:string;slug:string;}[]
posts
:awaitmodule"$lib/server/database"db.
functiongetPostSummaries():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 -->{@renderchildren()}</main><aside><h2>More posts</h2><ul>{#eachdata.postsaspost}<li><ahref="/blog/{post.slug}">{post.title}</a></li>{/each}</ul></aside>
<scriptlang="ts">importtype{ LayoutProps }from'./$types';let{ data,children }:LayoutProps=$props();</script><main><!-- +page.svelte is `@render`ed here -->{@renderchildren()}</main><aside><h2>More posts</h2><ul>{#eachdata.postsaspost}<li><ahref="/blog/{post.slug}">{post.title}</a></li>{/each}</ul></aside>
Legacy mode

LayoutProps was added in 2.16.0. In earlier versions, properties had to be typed individually:

+layout
/**@type{{ data: import('./$types').LayoutData, children: Snippet }}*/let{letdata:anydata,letchildren:anychildren}=
function$props():anynamespace$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
();
importtype{importLayoutDataLayoutData}from'./$types';let{letdata:LayoutDatadata,letchildren:Snippetchildren}:{data:LayoutDatadata:importLayoutDataLayoutData,children:Snippetchildren:typeSnippet=/*unresolved*/anySnippet}=
function$props():anynamespace$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
();

Data returned from layoutload functions is available to child+layout.svelte components and the+page.svelte component as well as the layout that it ‘belongs’ to.

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` functionletindex=$derived(data.posts.findIndex(post=>post.slug===page.params.slug));letnext=$derived(data.posts[index+1]);</script><h1>{data.post.title}</h1><div>{@htmldata.post.content}</div>{#ifnext}<p>Next post: <ahref="/blog/{next.slug}">{next.title}</a></p>{/if}
<scriptlang="ts">import{ page }from'$app/state';importtype{ PageProps }from'./$types';let{ data }:PageProps=$props();// we can access `data.posts` because it's returned from// the parent layout `load` functionletindex=$derived(data.posts.findIndex(post=>post.slug===page.params.slug));letnext=$derived(data.posts[index+1]);</script><h1>{data.post.title}</h1><div>{@htmldata.post.content}</div>{#ifnext}<p>Next post: <ahref="/blog/{next.slug}">{next.title}</a></p>{/if}

If multipleload functions return data with the same key, the last one ‘wins’ — the result of a layoutload returning{ a: 1, b: 2 } and a pageload returning{ b: 3, c: 4 } would be{ a: 1, b: 3, c: 4 }.

page.data

The+page.svelte component, and each+layout.svelte component above it, has access to its own data plus all the data from its parents.

In some cases, we might need the opposite — a parent layout might need to access page data or data from a child layout. For example, the root layout might want to access atitle property returned from aload function in+page.js or+page.server.js. This can be done withpage.data:

src/routes/+layout
<script>import{ page }from'$app/state';</script><svelte:head><title>{page.data.title}</title></svelte:head>
<scriptlang="ts">import{ page }from'$app/state';</script><svelte:head><title>{page.data.title}</title></svelte:head>

Type information forpage.data is provided byApp.PageData.

Legacy mode

$app/state was added in SvelteKit 2.12. If you’re using an earlier version or are using Svelte 4, use$app/stores instead.It provides apage store with the same interface that you can subscribe to, e.g.$page.data.title.

Universal vs server

As we’ve seen, there are two types ofload function:

  • +page.js and+layout.js files exportuniversalload functions that run both on the server and in the browser
  • +page.server.js and+layout.server.js files exportserverload functions that only run server-side

Conceptually, they’re the same thing, but there are some important differences to be aware of.

When does which load function run?

Serverload functionsalways run on the server.

By default, universalload functions run on the server during SSR when the user first visits your page. They will then run again during hydration, reusing any responses fromfetch requests. All subsequent invocations of universalload functions happen in the browser. You can customize the behavior throughpage options. If you disableserver-side rendering, you’ll get an SPA and universalload functionsalways run on the client.

If a route contains both universal and serverload functions, the serverload runs first.

Aload function is invoked at runtime, unless youprerender the page — in that case, it’s invoked at build time.

Input

Both universal and serverload functions have access to properties describing the request (params,route andurl) and various functions (fetch,setHeaders,parent,depends anduntrack). These are described in the following sections.

Serverload functions are called with aServerLoadEvent, which inheritsclientAddress,cookies,locals,platform andrequest fromRequestEvent.

Universalload functions are called with aLoadEvent, which has adata property. If you haveload functions in both+page.js and+page.server.js (or+layout.js and+layout.server.js), the return value of the serverload function is thedata property of the universalload function’s argument.

Output

A universalload function can return an object containing any values, including things like custom classes and component constructors.

A serverload function must return data that can be serialized withdevalue — anything that can be represented as JSON plus things likeBigInt,Date,Map,Set andRegExp, or repeated/cyclical references — so that it can be transported over the network. Your data can includepromises, in which case it will be streamed to browsers. If you need to serialize/deserialize custom types, usetransport hooks.

When to use which

Serverload functions are convenient when you need to access data directly from a database or filesystem, or need to use private environment variables.

Universalload functions are useful when you need tofetch data from an external API and don’t need private credentials, since SvelteKit can get the data directly from the API rather than going via your server. They are also useful when you need to return something that can’t be serialized, such as a Svelte component constructor.

In rare cases, you might need to use both together — for example, you might need to return an instance of a custom class that was initialised with data from your server. When using both, the serverload return value isnot passed directly to the page, but to the universalload function (as thedata property):

src/routes/+page.server
/**@type{import('./$types').PageServerLoad}*/exportasyncfunction
functionload():Promise<{serverMessage:string;}>
@type{import('./$types').PageServerLoad}
load
() {
return{serverMessage:stringserverMessage:'hello from server load function'};}
importtype{
typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageServerLoad
}from'./$types';
exportconstconstload:PageServerLoadload:
typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageServerLoad=(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}*/exportasyncfunction
functionload({ 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'};}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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 serverload 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 serverload function (in+layout.server.js or+page.server.js), if any.

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

Using URL data

Often theload function depends on the URL in one way or another. For this, theload function provides you withurl,route andparams.

url

An instance ofURL, containing properties like theorigin,hostname,pathname andsearchParams (which contains the parsed query string as aURLSearchParams object).url.hash cannot be accessed duringload, since it is unavailable on the server.

In some environments this is derived from request headers during server-side rendering. If you’re usingadapter-node, for example, you may need to configure the adapter in order for the URL to be correct.

route

Contains the name of the current route directory, relative tosrc/routes:

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

Theconsole module provides a simple debugging console that is similar to theJavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • AConsole class with methods such asconsole.log(),console.error() andconsole.warn() that can be used to write to any Node.js stream.
  • A globalconsole instance configured to write toprocess.stdout andprocess.stderr. The globalconsole can be used without importing thenode:console module.

Warning: The global console object’s methods are neither consistentlysynchronous like the browser APIs they resemble, nor are they consistentlyasynchronous like all other Node.js streams. See thenote on process I/O formore information.

Example using the globalconsole:

console.log('hello world');// Prints: hello world, to stdoutconsole.log('hello %s','world');// Prints: hello world, to stdoutconsole.error(newError('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:3constname='Will Robinson';console.warn(`Danger${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to stderr

Example using theConsole class:

constout=getStreamSomehow();consterr=getStreamSomehow();constmyConsole=newconsole.Console(out,err);myConsole.log('hello world');// Prints: hello world, to outmyConsole.log('hello %s','world');// Prints: hello world, to outmyConsole.error(newError('Whoops, something bad happened'));// Prints: [Error: Whoops, something bad happened], to errconstname='Will Robinson';myConsole.warn(`Danger${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?:any,...optionalParams: any[]):void(+1overload)

Prints tostdout with newline. Multiple arguments can be passed, with thefirst used as the primary message and all additional used as substitutionvalues similar toprintf(3)(the arguments are all passed toutil.format()).

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

Seeutil.format() for more information.

@sincev0.1.100
log
(route:anyroute.id);// '/a/[b]/[...c]'
}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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
})=>{
varconsole:Console

Theconsole module provides a simple debugging console that is similar to theJavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • AConsole class with methods such asconsole.log(),console.error() andconsole.warn() that can be used to write to any Node.js stream.
  • A globalconsole instance configured to write toprocess.stdout andprocess.stderr. The globalconsole can be used without importing thenode:console module.

Warning: The global console object’s methods are neither consistentlysynchronous like the browser APIs they resemble, nor are they consistentlyasynchronous like all other Node.js streams. See thenote on process I/O formore information.

Example using the globalconsole:

console.log('hello world');// Prints: hello world, to stdoutconsole.log('hello %s','world');// Prints: hello world, to stdoutconsole.error(newError('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:3constname='Will Robinson';console.warn(`Danger${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to stderr

Example using theConsole class:

constout=getStreamSomehow();consterr=getStreamSomehow();constmyConsole=newconsole.Console(out,err);myConsole.log('hello world');// Prints: hello world, to outmyConsole.log('hello %s','world');// Prints: hello world, to outmyConsole.error(newError('Whoops, something bad happened'));// Prints: [Error: Whoops, something bad happened], to errconstname='Will Robinson';myConsole.warn(`Danger${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?:any,...optionalParams: any[]):void(+1overload)

Prints tostdout with newline. Multiple arguments can be passed, with thefirst used as the primary message and all additional used as substitutionvalues similar toprintf(3)(the arguments are all passed toutil.format()).

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

Seeutil.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. forsrc/routes/blog/[slug], it would be/blog/[slug]. It isnull when no route is matched.

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

params

params is derived fromurl.pathname androute.id.

Given aroute.id of/a/[b]/[...c] and aurl.pathname of/a/x/y/z, theparams object would look like this:

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

Making fetch requests

To get data from an external API or a+server.js handler, you can use the providedfetch function, which behaves identically to thenativefetch web API with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits thecookie andauthorization 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 thetext,json andarrayBuffer methods of theResponse object. Note that headers willnot be serialized, unless explicitly included viafilterSerializedResponseHeaders.
  • During hydration, the response will be read from the HTML, guaranteeing consistency and preventing an additional network request - if you received a warning in your browser console when using the browserfetch instead of theloadfetch, this is why.
src/routes/items/[id]/+page
/**@type{import('./$types').PageLoad}*/exportasyncfunction
functionload({ fetch,params }:{fetch:any;params:any;}):Promise<{item:any;}>
@type{import('./$types').PageLoad}
load
({fetch:anyfetch,params:anyparams}) {
constconstres:anyres=awaitfetch:anyfetch(`/api/items/${params:anyparams.id}`);constconstitem:anyitem=awaitconstres:anyres.json();return{item:anyitem};}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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 thenativefetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits thecookie andauthorization 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 thetext andjson methods of theResponse object. Note that headers willnot be serialized, unless explicitly included viafilterSerializedResponseHeaders
  • 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 cookieshere

fetch
,params:Record<string,any>

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

params
})=>{
constconstres:Responseres=awaitfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)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}`);
constconstitem:anyitem=awaitconstres:Responseres.Body.json():Promise<any>json();return{item:anyitem};};

Cookies

A serverload function can get and setcookies.

src/routes/+layout.server
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';/**@type{import('./$types').LayoutServerLoad}*/exportasyncfunctionfunctionload(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
}) {
constconstsessionid: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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid');
return{
user:{name:string;avatar:string;}
user
:awaitmodule"$lib/server/database"db.
functiongetUser(sessionid:string|undefined):Promise<{name:string;avatar:string;}>
getUser
(constsessionid:string|undefinedsessionid)
};}
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';importtype{typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad}from'./$types';exportconstconstload:LayoutServerLoadload:typeLayoutServerLoad=(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
})=>{
constconstsessionid: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 withcookies.set, or from the request headers.

@paramname the name of the cookie
@paramopts the options, passed directly tocookie.parse. See documentationhere
get
('sessionid');
return{
user:{name:string;avatar:string;}
user
:awaitmodule"$lib/server/database"db.
functiongetUser(sessionid:string|undefined):Promise<{name:string;avatar:string;}>
getUser
(constsessionid:string|undefinedsessionid)
};};

Cookies will only be passed through the providedfetch function if the target host is the same as the SvelteKit application or a more specific subdomain of it.

For example, if SvelteKit is serving my.domain.com:

  • domain.com WILL NOT receive cookies
  • my.domain.com WILL receive cookies
  • api.domain.com WILL NOT receive cookies
  • sub.my.domain.com WILL receive cookies

Other cookies will not be passed whencredentials: 'include' is set, because SvelteKit does not know which domain which cookie belongs to (the browser does not pass this information along), so it’s not safe to forward any of them. Use thehandleFetch hook to work around it.

Headers

Both server and universalload functions have access to asetHeaders function that, when running on the server, can set headers for the response. (When running in the browser,setHeaders has no effect.) This is useful if you want the page to be cached, for example:

src/routes/products/+page
/**@type{import('./$types').PageLoad}*/exportasyncfunction
functionload({ fetch,setHeaders }:{fetch:any;setHeaders:any;}):Promise<any>
@type{import('./$types').PageLoad}
load
({fetch:anyfetch,setHeaders:anysetHeaders}) {
constconsturl:"https://cms.example.com/products.json"url=`https://cms.example.com/products.json`;constconstresponse:anyresponse=awaitfetch:anyfetch(consturl:"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:constresponse:anyresponse.headers.get('age'),'cache-control':constresponse:anyresponse.headers.get('cache-control')});returnconstresponse:anyresponse.json();}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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 thenativefetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits thecookie andauthorization 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 thetext andjson methods of theResponse object. Note that headers willnot be serialized, unless explicitly included viafilterSerializedResponseHeaders
  • 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 cookieshere

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
exportasyncfunctionload({ fetch,setHeaders }) {consturl=`https://cms.example.com/articles.json`;constresponse=awaitfetch(url);setHeaders({age:response.headers.get('age'),'cache-control':response.headers.get('cache-control')});returnresponse.json();}

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

You cannot add aset-cookie header withsetHeaders — use thecookies API in a server-onlyload function instead.

setHeaders has no effect when aload function runs in the browser.

setHeaders
})=>{
constconsturl:"https://cms.example.com/products.json"url=`https://cms.example.com/products.json`;constconstresponse:Responseresponse=awaitfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)fetch(consturl:"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
exportasyncfunctionload({ fetch,setHeaders }) {consturl=`https://cms.example.com/articles.json`;constresponse=awaitfetch(url);setHeaders({age:response.headers.get('age'),'cache-control':response.headers.get('cache-control')});returnresponse.json();}

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

You cannot add aset-cookie header withsetHeaders — use thecookies API in a server-onlyload function instead.

setHeaders has no effect when aload function runs in the browser.

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

Setting the same header multiple times (even in separateload functions) is an error. You can only set a given header once using thesetHeaders function. You cannot add aset-cookie header withsetHeaders — usecookies.set(name, value, options) instead.

Using parent data

Occasionally it’s useful for aload function to access data from a parentload function, which can be done withawait parent():

src/routes/+layout
/**@type{import('./$types').LayoutLoad}*/exportfunction
functionload():{a:number;}
@type{import('./$types').LayoutLoad}
load
() {
return{a:numbera:1};}
importtype{
typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
LayoutLoad
}from'./$types';
exportconstconstload:LayoutLoadload:
typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typeLayoutLoad=(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}*/exportasyncfunction
functionload({ parent }:{parent:any;}):Promise<{b:any;}>
@type{import('./$types').LayoutLoad}
load
({parent:anyparent}) {
const{consta:anya}=awaitparent:anyparent();return{b:anyb:consta:anya+1};}
importtype{
typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
LayoutLoad
}from'./$types';
exportconstconstload:LayoutLoadload:
typeLayoutLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typeLayoutLoad=(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.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

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

await parent() returns data from parent+layout.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
();
return{b:anyb:consta:anya+1};};
src/routes/abc/+page
/**@type{import('./$types').PageLoad}*/exportasyncfunction
functionload({ parent }:{parent:any;}):Promise<{c:any;}>
@type{import('./$types').PageLoad}
load
({parent:anyparent}) {
const{consta:anya,constb:anyb}=awaitparent:anyparent();return{c:anyc:consta:anya+constb:anyb};}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
})=>{
const{consta:anya,constb:anyb}=awaitparent:()=>Promise<Record<string,any>>

await parent() returns data from parent+layout.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
();
return{c:anyc:consta:anya+constb: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>
<scriptlang="ts">importtype{ PageProps }from'./$types';let{ data }:PageProps=$props();</script><!-- renders `1 + 2 = 3` --><p>{data.a} + {data.b} = {data.c}</p>

Notice that theload function in+page.js receives the merged data from both layoutload functions, not just the immediate parent.

Inside+page.server.js and+layout.server.js,parent returns data from parent+layout.server.js files.

In+page.js or+layout.js it will return data from parent+layout.js files. However, a missing+layout.js is treated as a({ data }) => data function, meaning that it will also return data from parent+layout.server.js files that are not ‘shadowed’ by a+layout.js file

Take care not to introduce waterfalls when usingawait parent(). Here, for example,getData(params) does not depend on the result of callingparent(), so we should call it first to avoid a delayed render.

+page
/**@type{import('./$types').PageLoad}*/exportasyncfunctionfunctionload(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.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
}) {
const parentData = await parent();const
constdata:{meta:any;}
data
=await
functiongetData(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
);
constconstparentData:Record<string,any>parentData=awaitparent:()=>Promise<Record<string,any>>

await parent() returns data from parent+layout.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
();
return{...
constdata:{meta:any;}
data
,
meta:anymeta:{...constparentData:Record<string,any>parentData.meta,...
constdata:{meta:any;}
data
.meta:anymeta}
};}
importtype{typePageLoad=(event:LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageLoad}from'./$types';exportconstconstload:PageLoadload:typePageLoad=(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.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

parent
})=>{
const parentData = await parent();const
constdata:{meta:any;}
data
=await
functiongetData(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
);
constconstparentData:Record<string,any>parentData=awaitparent:()=>Promise<Record<string,any>>

await parent() returns data from parent+layout.jsload 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 usingawait parent(). If for example you only want to merge parent data into the returned output, call itafter fetching your other data.

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

Errors

If an error is thrown duringload, the nearest+error.svelte will be rendered. Forexpected errors, use theerror helper from@sveltejs/kit to specify the HTTP status code and an optional message:

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

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

@paramstatus TheHTTP 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}*/exportfunctionfunctionload(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 theserver handle hook.

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

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

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

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

@paramstatus TheHTTP 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 theserver handle hook.

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

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

@paramstatus TheHTTP 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{functionerror(status:number,body:App.Error):never(+1overload)

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

@paramstatus TheHTTP 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';
importtype{typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad}from'./$types';exportconstconstload:LayoutServerLoadload:typeLayoutServerLoad=(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 theserver handle hook.

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

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

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

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

@paramstatus TheHTTP 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 theserver handle hook.

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

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

@paramstatus TheHTTP 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');
}};

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

If anunexpected error is thrown, SvelteKit will invokehandleError and treat it as a 500 Internal Error.

In SvelteKit 1.x you had tothrow the error yourself

Redirects

To redirect users, use theredirect helper from@sveltejs/kit to specify the location to which they should be redirected alongside a3xx status code. Likeerror(...), callingredirect(...) will throw an exception, making it easy to stop execution from inside helper functions.

src/routes/user/+layout.server
import{functionredirect(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 TheHTTP 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}*/exportfunctionfunctionload(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 theserver handle hook.

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

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

locals
.
App.Locals.user?:{name:string;}|undefined
user
) {
functionredirect(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 TheHTTP 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{functionredirect(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 TheHTTP 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';
importtype{typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad}from'./$types';exportconstconstload:LayoutServerLoadload:typeLayoutServerLoad=(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 theserver handle hook.

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

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

locals
.
App.Locals.user?:{name:string;}|undefined
user
) {
functionredirect(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 TheHTTP 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');
}};

Don’t useredirect() inside atry {...} block, as the redirect will immediately trigger the catch statement.

In the browser, you can also navigate programmatically outside of aload function usinggoto from$app.navigation.

In SvelteKit 1.x you had tothrow theredirect yourself

Streaming with promises

When using a serverload, promises will be streamed to the browser as they resolve. This is useful if you have slow, non-essential data, since you can start rendering the page before all the data is available:

src/routes/blog/[slug]/+page.server
/**@type{import('./$types').PageServerLoad}*/exportasyncfunctionfunctionload(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
:
constloadComments:(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
constloadPost:(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)
};}
importtype{typePageServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageServerLoad}from'./$types';exportconstconstload:PageServerLoadload:typePageServerLoad=(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
:
constloadComments:(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
constloadPost:(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)
};};

This is useful for creating skeleton loading states, for example:

src/routes/blog/[slug]/+page
<script>/**@type{import('./$types').PageProps}*/let{ data }=$props();</script><h1>{data.post.title}</h1><div>{@htmldata.post.content}</div>{#awaitdata.comments}Loading comments...{:thencomments}{#eachcommentsascomment}<p>{comment.content}</p>{/each}{:catcherror}<p>error loading comments: {error.message}</p>{/await}
<scriptlang="ts">importtype{ PageProps }from'./$types';let{ data }:PageProps=$props();</script><h1>{data.post.title}</h1><div>{@htmldata.post.content}</div>{#awaitdata.comments}Loading comments...{:thencomments}{#eachcommentsascomment}<p>{comment.content}</p>{/each}{:catcherror}<p>error loading comments: {error.message}</p>{/await}

When streaming data, be careful to handle promise rejections correctly. More specifically, the server could crash with an “unhandled promise rejection” error if a lazy-loaded promise fails before rendering starts (at which point it’s caught) and isn’t handling the error in some way. When using SvelteKit’sfetch directly in theload function, SvelteKit will handle this case for you. For other promises, it is enough to attach a noop-catch to the promise to mark it as handled.

src/routes/+page.server
/**@type{import('./$types').PageServerLoad}*/exportfunction
functionload({ fetch }:{fetch:any;}):{ok_manual:Promise<never>;ok_fetch:any;dangerous_unhandled:Promise<never>;}
@type{import('./$types').PageServerLoad}
load
({fetch:anyfetch}) {
constconstok_manual:Promise<never>ok_manual=varPromise: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
();
constok_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:varPromise: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
()
};}
importtype{
typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageServerLoad
}from'./$types';
exportconstconstload:PageServerLoadload:
typePageServerLoad=(event:Kit.ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageServerLoad=(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 thenativefetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits thecookie andauthorization 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 thetext andjson methods of theResponse object. Note that headers willnot be serialized, unless explicitly included viafilterSerializedResponseHeaders
  • 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 cookieshere.

fetch
})=>{
constconstok_manual:Promise<never>ok_manual=varPromise: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
();
constok_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> (+1overload)fetch('/fetch/that/could/fail'),dangerous_unhandled:Promise<never>dangerous_unhandled:varPromise: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
()
};};

On platforms that do not support streaming, such as AWS Lambda or Firebase, responses will be buffered. This means the page will only render once all promises resolve. If you are using a proxy (e.g. NGINX), make sure it does not buffer responses from the proxied server.

Streaming data will only work when JavaScript is enabled. You should avoid returning promises from a universalload function if the page is server rendered, as these arenot streamed — instead, the promise is recreated when the function reruns in the browser.

The headers and status code of a response cannot be changed once the response has started streaming, therefore you cannotsetHeaders or throw redirects inside a streamed promise.

In SvelteKit 1.x top-level promises were automatically awaited, only nested promises were streamed.

Parallel loading

When rendering (or navigating to) a page, SvelteKit runs allload functions concurrently, avoiding a waterfall of requests. During client-side navigation, the result of calling multiple serverload functions are grouped into a single response. Once allload functions have returned, the page is rendered.

Rerunning load functions

SvelteKit tracks the dependencies of eachload function to avoid rerunning it unnecessarily during navigation.

For example, given a pair ofload functions like these...

src/routes/blog/[slug]/+page.server
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';/**@type{import('./$types').PageServerLoad}*/exportasyncfunctionfunctionload(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
:awaitmodule"$lib/server/database"db.
functiongetPost(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*asmodule"$lib/server/database"dbfrom'$lib/server/database';importtype{typePageServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>PageServerLoad}from'./$types';exportconstconstload:PageServerLoadload:typePageServerLoad=(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
:awaitmodule"$lib/server/database"db.
functiongetPost(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*asmodule"$lib/server/database"dbfrom'$lib/server/database';/**@type{import('./$types').LayoutServerLoad}*/exportasyncfunctionfunctionload(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
:awaitmodule"$lib/server/database"db.
functiongetPostSummaries():Promise<Array<{title:string;slug:string;}>>
getPostSummaries
()
};}
import*asmodule"$lib/server/database"dbfrom'$lib/server/database';importtype{typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad}from'./$types';exportconstconstload:LayoutServerLoadload:typeLayoutServerLoad=(event:ServerLoadEvent<Record<string,any>,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>LayoutServerLoad=async()=>{return{
posts:{title:string;slug:string;}[]
posts
:awaitmodule"$lib/server/database"db.
functiongetPostSummaries():Promise<Array<{title:string;slug:string;}>>
getPostSummaries
()
};};

...the one in+page.server.js will rerun if we navigate from/blog/trying-the-raw-meat-diet to/blog/i-regret-my-choices becauseparams.slug has changed. The one in+layout.server.js will not, because the data is still valid. In other words, we won’t calldb.getPostSummaries() a second time.

Aload function that callsawait parent() will also rerun if a parentload function is rerun.

Dependency tracking does not applyafter theload function has returned — for example, accessingparams.x inside a nestedpromise will not cause the function to rerun whenparams.x changes. (Don’t worry, you’ll get a warning in development if you accidentally do this.) Instead, access the parameter in the main body of yourload function.

Search parameters are tracked independently from the rest of the url. For example, accessingevent.url.searchParams.get("x") inside aload function will make thatload function re-run when navigating from?x=1 to?x=2, but not when navigating from?x=1&y=1 to?x=1&y=2.

Untracking dependencies

In rare cases, you may wish to exclude something from the dependency tracking mechanism. You can do this with the provideduntrack function:

src/routes/+page
/**@type{import('./$types').PageLoad}*/exportasyncfunction
functionload({ 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 rerunif(untrack:anyuntrack(()=>url:anyurl.pathname==='/')) {return{message:stringmessage:'Welcome!'};}}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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
exportasyncfunctionload({ untrack,url }) {// Untrack url.pathname so that path changes don't trigger a rerunif(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 rerunif(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
exportasyncfunctionload({ untrack,url }) {// Untrack url.pathname so that path changes don't trigger a rerunif(untrack(()=>url.pathname==='/')) {return{ message:'Welcome!'};}}
untrack
(()=>url:URL

The URL of the current page

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

Manual invalidation

You can also rerunload functions that apply to the current page usinginvalidate(url), which reruns allload functions that depend onurl, andinvalidateAll(), which reruns everyload function. Server load functions will never automatically depend on a fetchedurl to avoid leaking secrets to the client.

Aload function depends onurl if it callsfetch(url) ordepends(url). Note thaturl can be a custom identifier that starts with[a-z]::

src/routes/random-number/+page
/**@type{import('./$types').PageLoad}*/exportasyncfunction
functionload({ 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...constconstresponse:anyresponse=awaitfetch:anyfetch('https://api.example.com/random-number');// ...or when `invalidate('app:random')` is calleddepends:anydepends('app:random');return{number:anynumber:awaitconstresponse:anyresponse.json()};}
importtype{
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>
PageLoad
}from'./$types';
exportconstconstload:PageLoadload:
typePageLoad=(event:Kit.LoadEvent<Record<string,any>,Record<string,any>|null,Record<string,any>,string|null>)=>MaybePromise<void|Record<string,any>>typePageLoad=(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 thenativefetch web API, with a few additional features:

  • It can be used to make credentialed requests on the server, as it inherits thecookie andauthorization 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 thetext andjson methods of theResponse object. Note that headers willnot be serialized, unless explicitly included viafilterSerializedResponseHeaders
  • 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 cookieshere

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

This function declares that theload function has adependency on one or more URLs or custom identifiers, which can subsequently be used withinvalidate() to causeload to rerun.

Most of the time you won’t need this, asfetch callsdepends on your behalf — it’s only necessary if you’re using a custom API client that bypassesfetch.

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

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

The following example shows how to usedepends to register a dependency on a custom identifier, which isinvalidated after a button click, making theload function rerun.

src/routes/+page
letcount=0;exportasyncfunctionload({ depends }) {depends('increase:count');return{ count:count++};}
src/routes/+page
&#x3C;script>import { invalidate } from '$app/navigation';let { data } = $props();const increase = async () => {awaitinvalidate('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...constconstresponse:Responseresponse=awaitfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)fetch('https://api.example.com/random-number');// ...or when `invalidate('app:random')` is calleddepends:(...deps:Array<`${string}:${string}`>)=>void

This function declares that theload function has adependency on one or more URLs or custom identifiers, which can subsequently be used withinvalidate() to causeload to rerun.

Most of the time you won’t need this, asfetch callsdepends on your behalf — it’s only necessary if you’re using a custom API client that bypassesfetch.

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

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

The following example shows how to usedepends to register a dependency on a custom identifier, which isinvalidated after a button click, making theload function rerun.

src/routes/+page
letcount=0;exportasyncfunctionload({ depends }) {depends('increase:count');return{ count:count++};}
src/routes/+page
&#x3C;script>import { invalidate } from '$app/navigation';let { data } = $props();const increase = async () => {awaitinvalidate('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:awaitconstresponse: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();functionrerunLoadFunction() {// any of these will cause the `load` function to reruninvalidate('app:random');invalidate('https://api.example.com/random-number');invalidate(url=>url.href.includes('random-number'));invalidateAll();}</script><p>random number: {data.number}</p><buttononclick={rerunLoadFunction}>Update random number</button>
<scriptlang="ts">import{ invalidate,invalidateAll }from'$app/navigation';importtype{ PageProps }from'./$types';let{ data }:PageProps=$props();functionrerunLoadFunction() {// any of these will cause the `load` function to reruninvalidate('app:random');invalidate('https://api.example.com/random-number');invalidate(url=>url.href.includes('random-number'));invalidateAll();}</script><p>random number: {data.number}</p><buttononclick={rerunLoadFunction}>Update random number</button>

When do load functions rerun?

To summarize, aload function will rerun in the following situations:

  • It references a property ofparams whose value has changed
  • It references a property ofurl (such asurl.pathname orurl.search) whose value has changed. Properties inrequest.url arenot tracked
  • It callsurl.searchParams.get(...),url.searchParams.getAll(...) orurl.searchParams.has(...) and the parameter in question changes. Accessing other properties ofurl.searchParams will have the same effect as accessingurl.search.
  • It callsawait parent() and a parentload function reran
  • A childload function callsawait parent() and is rerunning, and the parent is a server load function
  • It declared a dependency on a specific URL viafetch (universal load only) ordepends, and that URL was marked invalid withinvalidate(url)
  • All activeload functions were forcibly rerun withinvalidateAll()

params andurl can change in response to a<a href=".."> link click, a<form> interaction, agoto invocation, or aredirect.

Note that rerunning aload function will update thedata prop inside the corresponding+layout.svelte or+page.svelte; it doesnot cause the component to be recreated. As a result, internal state is preserved. If this isn’t what you want, you can reset whatever you need to reset inside anafterNavigate callback, and/or wrap your component in a{#key ...} block.

Implications for authentication

A couple features of loading data have important implications for auth checks:

  • Layoutload functions do not run on every request, such as during client side navigation between child routes.(When do load functions rerun?)
  • Layout and pageload functions run concurrently unlessawait parent() is called. If a layoutload throws, the pageload function runs, but the client will not receive the returned data.

There are a few possible strategies to ensure an auth check occurs before protected code.

To prevent data waterfalls and preserve layoutload caches:

  • Usehooks to protect multiple routes before anyload functions run
  • Use auth guards directly in+page.server.jsload functions for route specific protection

Putting an auth guard in+layout.server.js requires all child pages to callawait parent() before protected code. Unless every child page depends on returned data fromawait parent(), the other options will be more performant.

Using getRequestEvent

When running serverload functions, theevent object passed to the function as an argument can also be retrieved withgetRequestEvent. This allows shared logic (such as authentication guards) to access information about the current request without it needing to be passed around.

For example, you might have a function that requires users to be logged in, and redirects them to/login if not:

src/lib/server/auth
import{functionredirect(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 TheHTTP 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{functiongetRequestEvent():RequestEvent

Returns the currentRequestEvent. Can be used inside server hooks, serverload functions, actions, and endpoints (and functions called by them).

In environments withoutAsyncLocalStorage, this must be called synchronously (i.e. not after anawait).

@since2.20.0
getRequestEvent
}from'$app/server';
exportfunctionfunctionrequireLogin():UserrequireLogin() {const{constlocals:App.Locals

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

locals
,consturl:URL

The requested URL.

url
}=functiongetRequestEvent():RequestEvent

Returns the currentRequestEvent. Can be used inside server hooks, serverload functions, actions, and endpoints (and functions called by them).

In environments withoutAsyncLocalStorage, this must be called synchronously (i.e. not after anawait).

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

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

locals
.App.Locals.user?:User|undefineduser) {
constconstredirectTo:stringredirectTo=consturl:URL

The requested URL.

url
.URL.pathname: stringpathname+consturl:URL

The requested URL.

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

MDN Reference

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

@sincev10.0.0
URLSearchParams
({redirectTo:stringredirectTo});
functionredirect(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 TheHTTP 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?${constparams:URLSearchParamsparams}`);
}returnconstlocals:App.Locals

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

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

Now, you can callrequireLogin in anyload function (orform action, for example) to guarantee that the user is logged in:

+page.server
import{functionrequireLogin():UserrequireLogin}from'$lib/server/auth';exportfunction
functionload():{message:string;}
load
() {
constconstuser:Useruser=functionrequireLogin():UserrequireLogin();// `user` is guaranteed to be a user object here, because otherwise// `requireLogin` would throw a redirect and we wouldn't get herereturn{message:stringmessage:`hello${constuser:Useruser.User.name: stringname}!`};}

Further reading

Edit this page on GitHub llms.txt


[8]ページ先頭

©2009-2025 Movatter.jp