Svelte/Sapper vs Vue
Tags: svelte, sapper, vue, ssr
Published: 2020-09-01 15:14:06

_In which I highlight the gap between Sapper and Vue_

So I wrote a lovely article with examples comparing [Vue](https://vuejs.org/) and friends to [Svelte](https://svelte.dev/) and [Sapper](https://sapper.svelte.dev/).  But twice the draft refused to save and so I gave up.  The main point to get across is that `.vue` components are far more readable than `.svelte` components.  However on every count Svelte requires less code as is their mantra (and it's a good one). But there is one thing where Sapper doesn't quite measure up.

## **SSR and State Management**

While on the surface Server Side Rendering (SSR) is much easier in Sapper, there is one thing isn't quite there. How do we pass the server state back to the client.  First let's look at Vue

#### Vue SSR & Vuex

[Vuex](https://vuex.vuejs.org/) helps us manage state centrally in our Vue apps. If you follow the [guide](https://vuex.vuejs.org/guide/) the Vuex store is setup as a singleton.  It looks something like this.

```
import Vuex from 'vuex'

const store = new Vuex.Store({
  ...
})
export default store
```

This is fine on the client, we'll only ever have one store.  However when we run SSR we need to service many clients and requests and we can't mixup the store across those requests, so now it needs to look like this.
```
import Vuex from 'vuex'

export default function createStore(){
 return new Vuex.Store({
  ...
  })
}
``` 
Now you can initialise many stores for your many requests. The same principle applies to the Vue app itself as well as [Vue Router](https://router.vuejs.org/) and [Apollo](https://apollo.vuejs.org/). A quick example of that is as follows.
```
import Vue from 'vue'
import createStore from './store'

export default createApp(){

  const store = createStore()

  const app = new Vue({
    store
  })

  return { app }
}
```

in `entry-client.js`

```
import createApp from './app'

const { app } = createApp()

app.mount("#app")
```

On the server once our app has processed the route, mutated the state and rendered the HTML we need to pass the Vuex state to the client before it hydrates, otherwise it will hydrate from a fresh store and now your app will be out of step with your store (which is bad).  This is pretty straightforward and you can [read about it here](https://ssr.vuejs.org/guide/data.html#final-state-injection). In short the store state is dumped inside `<script>` tags in the server rendered HTML and when Vue is initialised on the client it slurps it up and updates the client state to match.

#### Sapper

If you have no idea what Sapper is, it's the equivalent of [Nuxt](https://nuxtjs.org/) but for Svelte. The creator, Rich Harris, has a [nice article](https://svelte.dev/blog/sapper-towards-the-ideal-web-app-framework) introducing Sapper.

Back to SSR, it's not quite the same in Sapper.  We don't have the same concept of a Vue class that we can initialise and then feed it things like routers, stores and Apollo clients.  In Svelte we have the concept of [stores](https://svelte.dev/tutorial/writable-stores), but as singletons.  

When the stores are written to on the server they hang around between requests. This is bad news, not only can you send a user incorrect data, you could send someone else's data (Yikes!).  So the best approach would be to not mutate the stores on the server. 

But we like having a store on the client and we want the state from the server to come down.  Sapper has a couple of approaches towards achieving this.

#### **Session Data**

On the server Sapper uses [sessions](https://sapper.svelte.dev/docs#Stores) for your user data which you can use to set data on the server and then pass down to the client.  

#### **Preload**

In the [preload](https://sapper.svelte.dev/docs/#Preloading) function we can fetch data server side before rendering. So in a component you can write something like this

```
<script context="module">
  export async function preload(page, session) {
     let animal = "dog";
   return { animal }
  }
</script>

<script>
  export let animal;
</script>

<p>
  { animal }
</p>
```

Then it's up to you on the client side to synchronise the store yourself in the `onMount` hook. Note that `onMount` is never called on the server so you can be confident that it is only running on the client.

The `preload` function however is comparable to [asyncData](https://nuxtjs.org/api/) from Nuxt.js and can run on both server AND the client. You can get around this by using the `process.browser` variable and only executing your server logic inside an if block, but this is cumbersome. 

#### Apollo Client

A big feature of Apollo is caching. In Vue, if we fetch some data server side with Apollo, we can pass down the Apollo state as we did with the Vuex state.  Like the above, you've got to handle the heavy lifting yourself and there is no recommended/documented way of doing it and some of things you enjoy (or at least I enjoy) in Vue SSR you just won't be able to achieve with Sapper. While it's not critical, without it you're missing out on an advantage of Apollo.

## Summary  

Should we all run off and learn Svelte to keep ourselves employed? 

The above state management and singleton problem aside... No, if you can do React or Vue then you're still good.  If you can't do either of those I would strongly recommend learning one if you want a job as a front end developer.  We are in for interesting times however as Svelte production bundles are much much smaller than Vue which means your Time To Interactive (TTI) is also going to be much smaller with Svelte.