SvelteKit makes it easy to to fetch data on the server side using the load()
function. This allows you to have your data present in the HTML server response for your page, improving your indexing performance with Google and other search engines. Let’s use a simple example:
<script context="module">
const apiUrl = 'https://jsonplaceholder.typicode.com/posts/1';
export async function load() {
const post = await (await fetch(apiUrl))?.json();
return {
props: {
post
}
};
}
</script>
<script>
export let post;
</script>
<h1>{post.title}</h1>
<p>{post.body}</p>
We can inspect the HTML of the page in the browser and see that the data is present in the HTML:
However, when inspecting the network tab we see this weird AJAX request for our data again on the frontend. But I thought load()
was supposed to work on the backend?
A subtle bug
It turns out that our original code above has a bug. A new user to SvelteKit might assume that load()
works like getServerSideProps() in Next.js, which runs only on the backend. However the load()
function runs both on the frontend and on the backend. So how do we then avoid it refetching data on the frontend?
The key is that load()
passes to us a function parameter that includes a lot of useful data and functions associated with our request. One of these is the fetch function, which is a special version of the normal Fetch API. The special thing about this version is that any requests will be inlined as JSON data in the HTML response. This allows us to skip the extra fetch when our load()
function runs on the frontend!
To use it, we simply have to destructure it from the incoming argument, overriding the default fetch
function.
Before:
export async function load() { ... }
After:
export async function load({ fetch }) { ... }
Now that we are using the special fetch function, we can observe that the frontend fetch request is gone, and we have new inlined JSON data that is used instead:
Here is the full correct implementation:
<script context="module">
const apiUrl = 'https://jsonplaceholder.typicode.com/posts/1';
export async function load({ fetch }) {
const post = await (await fetch(apiUrl))?.json();
return {
props: {
post
}
};
}
</script>
<script>
export let post;
</script>
<h1>{post.title}</h1>
<p>{post.body}</p>