Shared state of a store among multiple clients in Svelte Kit using SSR
Arnau Espin
Posted on April 30, 2022
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:
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>
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:
You can find the source code here
You can follow me on:
Posted on April 30, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.