Sveltekit — Streaming SSR
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.
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? ……