Sveltekit — Streaming SSR

Mohammed Anas
3 min readNov 22, 2023

--

I’ve been working on a project with Sveltekit with Supabase and DrizzleOrm. Everything worked fine when thing were running locally .All pages worked seamlessly with SSR.

But Once i pushed it to production, i was seeing 1–2 seconds delay with page navigation which is really not acceptable from a end user pov , it really kills the user experience.

If i opted for CSR it is going to kill SEO, So i chose to stream some of my data which is not important for initial page load , So we get immediate resoponse from the server , which is good for UX and at the same time i dont want to setup api routes which needs more Javascript on the client.

At the same time you get proper type safety when using Streaming , comparing it with using your own API routes

Setup Streaming in Sveltekit

This is for sveltekit v1 , v2 was relesed recently , if you wanna use it with v2 take a look at streaming here

We have created a sample sveltekit project, with two routes , /ssr and /streaming .

Lets emulate a costly computation with this code on both the endpoints server load

const promise = new Promise<number>((res) => {
setTimeout(() => {
res(Math.random());
}, 3000);
});

This is a simple promise which resolves after 3 seconds , Lets setup the basic routes

SSR Route

//+page.server.ts
import type { PageServerLoad } from "./$types";

export const load: PageServerLoad = async () => {
const promise = new Promise<number>((res) => {
setTimeout(() => {
res(Math.random());
}, 3000);
});
return { promise };
};
// +page.svelte
<script lang="ts">
export let data
</script>
<p>{data.promise}</p>

The top level promises are automatically awaited by sveltekit , you don’t need to manually await the data.

Streaming Route

//+page.server.ts
import type { PageServerLoad } from './$types';

export const load:PageServerLoad = async () => {
const promise = new Promise<number>((res)=>{
setTimeout(()=>{
res(Math.random())
},3000)
})
return {
stream:{
promise
}
}
};
// +page.svelte
<script lang="ts">
export let data;
$:({stream:{promise}}=data)
</script>

{#await promise}
<p>wait</p>
{:then data}
<p>{data}</p>
{/await}

If you want you use streaming in sveltekit , you need to return a promises as a nested object field , as we mentioned that top level responses are automatically awaited by sveltekit.

If we setup a basic navigation page and try to navigate to that page, you can see that , the SSR page take 3 seconds to render on the server and navigate while the streaming page gets rendered instantly.

Try it out here

Frameworks like Next.Js has built in support for loading Ui , and Streaming Responses, But fortunately setting it up in Sveltekit is relatively simple and straight forward.

Do note that you might need to setup a loading ui when the promise is awaited.

If you want to check out the project , take a look at this gitub repo.

You can also find the official sveltekit docs here.

Conclusion

I’ve found the Setup relatively useful on my project , From a UX perspective having a fast responding page is really important , So Why not give it a try? ……

--

--