Shared state of a store among multiple clients in Svelte Kit using SSR

aspnxdd

Arnau Espin

Posted on April 30, 2022

Shared state of a store among multiple clients in Svelte Kit using SSR

TLDR

Welcome to my first post, what I will show here is how to share a svelte store among multiple clients, that means if I have a store that displays a counter which is increased every 5 seconds, all the clients will see the same value of the counter, no matter when they opened our site.
That is useful when we attempt to feed the same data to all our clients and avoiding repetitive fetch requests, in case we have a data store that grabs info from an API, not a counter store.

Introduction

Hello, in this post I will describe how we can have a common svelte store that its state is shared among all our clients using it in the load function of Svelte-kit.

According to the Load function in the official docs

Mutating any shared state on the server will affect all clients, not just the current one.

Application

So, now you might be wondering, what is the use case for this?

Let's imagine that in our page index.svelte we are fetching the price of the top 10 stocks from an API that limits its requests to 20requests/min. If we have 3 clients opening our site at the same time (30 requests), the 3rd one will have an HTTP ERROR 429 (Too many requests).The data will be the same for all 3 clients, so do we need to fetch the data 3 times?

Well, if our site uses Client Side Rendering, yes, there is not another way to achieve it, but what if we use Server Side Rendering?

Of course, you could have a server running along and use Redis or something else, but how do you "cache" on a serverless website?

Using the approach I presented you, it sort of saves the state of the store and share it among all the clients, this way only 1 request is done by the first client. And this state will live until you update it in the setInterval

So, let's see some code on how to implement this.

Code

The following image describes what we are attempting to:
Shared state of a svelte store

In this example let's suppose we have a common store e.g. a Counter store, which is gonna increment by 1 every 5 seconds.


// store.ts
export const count = writable(0)
export const dateNow = writable(Date.now())

//index.svelte
<script context="module" lang="ts">
    import type { Load } from '@sveltejs/kit'
    import { get } from 'svelte/store'
    import { count, dateNow } from '../lib/store'

    // we need hydrate to be false for this to work
    export const hydrate = false 

    export const load: Load = async ({ fetch }) => {

        const FIVE_SEC_MS = 5 * 1000
        setInterval(() => {
            if (Date.now() - get(dateNow) > FIVE_SEC_MS) {
                count.update((n) => n + 1)
                dateNow.update(Date.now)
            }
        }, FIVE_SEC_MS)

        return {}
    }
</script>

<script lang="ts">
    let countValue: number = 0

    count.subscribe((value) => {
        countValue = value
    })

</script>

<span>
    {countValue}
</span>
Enter fullscreen mode Exit fullscreen mode

We have a setInterval which is gonna be running on the background every 5 seconds, in case there is a new client, the setInterval is gonna be rebuilt causing asynchronous behavior we are trying to avoid, this will happen no matter what, but in order to keep all the clients synced we use the dateNow store this way only 1 simultaneous update will occur.
Then we check that the (dateNow store - the current time) is greater than 5 seconds, this way we make sure that we keep all clients synced.

Video:

Video

You can find the source code here

You can follow me on:

πŸ’– πŸ’ͺ πŸ™… 🚩
aspnxdd
Arnau Espin

Posted on April 30, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related