Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sveltekit and SSR

I need a bit of help understanding SSR in the context of sveltekit. I noticed that the load method is called both on the server and the client and I cannot wrap my head around this. I guess it is needed to initialize the state of the client-side component, but why not just pass the props resulting from the SSR to the client?

What if a database request needs to be done during SSR? Now that same database request is repeated from the client? What if that is not even possible? I understand that I can use browser from $app/env to run different code on the server and in the browser but what props do I return? Is there any way to pass data from the server-side invocation of load to the client-side invocation?

like image 435
jpfollenius Avatar asked Jun 10 '21 12:06

jpfollenius


1 Answers

why not just pass the props resulting from the SSR to the client?

In order to do this, the props need to be serializable. You couldn't — for example — do something like this:

<script context="module">
  export async function load({ fetch }) {
    const data = await fetch('/data.json').then(r => r.json());
    const model = create_model(data);

    return {
      props: { model }
    };
  }
</script>

<script>
  export let model;
</script>

<h1>{$model.title}</h1>

Or you might need to dynamically import one component in one case, and a different component in another case, and pass that through as a prop.

There's another disadvantage to serializing the load output (which is what happened with SvelteKit's predecessor, Sapper) — in some cases, you might end up serializing a lot more data than you need to:

<script context="module">
  export async function load({ fetch }) {
    const compressed = await fetch('/compressed-data.json').then(r => r.json());
    const data = decompress(compressed);

    return {
      props: { data }
    };
  }
</script>

So SvelteKit runs load on both server and client. But it doesn't mean you're making unnecessary network requests. Anything you fetch in your load function is baked into the server-rendered HTML, meaning a) everything is contained in one request, b) the data used for server and client renders is guaranteed to be consistent, and c) any strings that appear in the fetched data and also appear in the markup are essentially 'free' because of gzip (or brotli).

What if a database request needs to be done during SSR?

You shouldn't be talking directly to the database in load, you should be creating an endpoint and requesting data with fetch. (We may add a method for auto-generating these endpoints in future, but it's not currently on the roadmap.)

like image 157
Rich Harris Avatar answered Oct 18 '22 15:10

Rich Harris