This is the first post in the “SvelteKit Internals” series. You can read more about the series here.
Loading data is essential for modern web applications, and each framework has its own approach. SvelteKit offers a straightforward and flexible way to load data into your app. Let's explore it in more detail.
In SvelteKit, a load function does exactly what it sounds like. It loads data into components. The function is called before the component is rendered, and will be re-run whenever the data changes or the component is re-rendered.
Per convention, load functions can be defined in the following files inside any folder in the src/routes directory:
+page.ts or +page.js
+page.server.ts or +page.server.js
+layout.ts or +layout.js
+layout.server.ts or +layout.server.js
Load functions also have access to some properties of the current request, such as params , url , locals , cookies , etc.
Shared vs Server-only load functions
Depending on your needs, you can define load functions to run on both the client and the server, or only on the server. My rule of thumb to decide which one to use is:
If I need to use a private environment variable, I use a server-only load function.
For the other cases, I use a shared load function.
The important thing to remember here is that shared load functions are run on both the client and the server. That means you should avoid using them for anything that you don’t want to be exposed to the client. Think of database credentials, API keys, or any other sensitive information.
Another thing to know about is the convention for server vs shared load functions. Server-only load functions are defined in files with the .server suffix (e.g. +page.server.ts ). Shared load functions are defined in files without the .server suffix (e.g. +page.ts ).
SvelteKit also does a lot to guide the developer in the right direction. For example, if you try to use a private environment variable ( $env/static/private or $env/runtime/private ) in a shared load function, you’ll get an error both in the browser and in the terminal.
Returning data and adding logic in load functions
In most cases, you will be returning JSON data from your load functions. But you can also do other things like redirects, returning errors, etc...
Here are a few examples of what you can do:
Accessing the load function data from the component
If your load function returns a JSON object, you can accesst it in the component using the data prop:
In the case of our Pokémon example, we can access the list of Pokémon and use it in the component in the component like this:
Using lang="ts" is optional, but it helps with type checking and autocompletion.
Merged load function data and inheritance
A child route will inherit from its parents' routes load functions data. Also, if you have a layout load function, all the child routes will inherit from its data as well.
Let’s say you have the following structure:
If src/routes/+layout.ts load function returns some data, then it can be accessed in src/routes/pokemons/+page.svelte and src/routes/pokemons/[slug]/+page.svelte . Same thing goes for src/routes/pokemons/+page.ts data that will be accessible in src/routes/pokemons/[slug]/+page.svelte .
There is no need to manually merge those data. SvelteKit will make them available in data prop of the component.
Additionally, to being able to access parents load data in child components, you can also access them in the child load function. This is possible using await parent() .
In my opinion, SvelteKit way of handling data loading and access is one of the thing that makes the experience of building a SvelteKit app so enjoyable. It’s simple, intuitive, and it just works.
You can read more about load functions in the SvelteKit documentation.