javascriptsveltesveltekitweb-frameworks

How to Pass Data from Server using SSR in SvelteKit?


I'm used to using Express with a templating engine, like Handlebars. I want to start working with Svelte and SvelteKit, but I'm unsure how to start working with both. I am stuck on passing data to the frontend from the server. In Express, I'd normally connect to the database, and then pass the data to res.render, where the templating engine would then take over. So far, I think I have to run a handle function to pass the data, and then I can access it from my page. But it seems that the handle function runs for every request, and if all my pages require different data, does that mean I have to use a giant switch statement or something for every page?

Can anybody tell me if that's the right way to pass data over, or if there's a better way. Sorry, I'm fairly new to metaf rameworks and Svelte.


Solution

  • The accepted answer below was written before a serious overhaul of how SvelteKit works in September 2022, here is a new answer:

    Routing is based on directories, where one directory corresponds to one route. In this directory you can find several files, most importantly +page.svelte, this is your 'page component' and where most of your code will go. One of the props is a special prop named data, which can be used to pass data to the page.

    <script>
      export let data
    </script>
    

    In order to do so, you can use the load function in two different files: +page.js and +page.server.js.

    export const load = async () => {
      return {
        // this object is sent to the data prop.
      }
    }
    

    The difference between the two files is that +page.js will initially load on the server and then always on the client, while +page.server.js will always run on the server. (during client navigation this data is fetched using a regular fetch command and then passed to the component).

    This means that most likely you will want to put your database connection and calls in +page.server.js.

    old answer

    There are two ways to achieve what you want to do. Let for both cases assume you have an about page and want to show dynamic data on this page like some team members. You would have a file called about.svelte (this makes the /about route) with in it something like:

    <script>
      export let team = [];
    </script>
    {#each team as member}
      ...
    {/each}
    

    Now how to get the team data to the page itself ?

    the load function

    The first option is the load function, this is a function that runs before the page is loaded and can be used to fetch data for this page. You would put the following block in about.svelte, usually before the other script block:

    <script context="module">
      export async function load({ fetch }) {
        const team = await fetch('/api/team').then(res => res.json());
        return {
          props: {
            team
          }
        }
      }
    </script>
    

    Important to note with this one is that you need some sort of api (/api/team in this case) that can give you the data.

    a page endpoint

    The second option is to make a so called page endpoint this acts as a kind of api and lives next to the page itself. In the same folder as about.svelte add a file about.js:

    export async function get() {
      const team = []; // add team data here somehow
      return {
       status: 200,
       body: {
         team
       }
    }
    

    what's the difference ?

    When to use which approach is mostly up to you, but you have to remember the following two things: