Useful Snippets

Welcome!


This blog is used to collect useful snippets related to Linux, PHP, MySQL and more. Feel free to post comments with improvements or questions!

RSS Latest posts from my personal blog


Most viewed posts


Subscribe to RSS feed


Avoiding subtle data fetching bugs with the SvelteKit load() function

Stanislav KhromovStanislav Khromov

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>

Web Developer at Aftonbladet (Schibsted Media Group)
Any opinions on this blog are my own and do not reflect the views of my employer.
LinkedIn
Twitter
WordPress.org Profile
Visit my other blog

Comments 0
There are currently no comments.