Currently, with Svelte 2, you can pass data from server to client like so:
// server.js
app.use(sapper.middleware({
store: req => ({
user: req.session && req.session.user
})
})
// client.js
sapper.start({
target,
store: data => new Store(data)
})
Behind the scenes, Sapper handles [de]serialization.
This is the accepted way to handle problems related to authentication, because user data has a couple of important characteristics:
But Svelte 3 doesn't have global stores that are passed around in quite the same way. One option would be to generate props, and rely on the developer to pass them around as necessary (including via layout components). This would be cumbersome, and would encourage developers to populate stores from inside components, which makes accidental data leakage significantly more likely.
A second option is to create the store on the generated app:
// generated code
import { writable } from 'svelte/store';
export const store = writable(__SAPPER__.store); // serialized and included on the page
// anywhere inside your app
<script>
import { store } as app from '@sapper/app'; // see #551
</script>
{#if $store.user}
<h1>Hello {$store.user.name}!</h1>
{:else}
<p>please <a href="login">log in</a></p>
{/if}
(See #551 for an explanation of @sapper/app.)
Does that make sense? Is store the right name? (session?)
Just realised this doesn't actually work. If store is just something exported by the app, there's no way to prevent leakage.
Instead, it needs to be tied to rendering, which means we need to use the context API. Sapper needs to provide a top level component that sets the store as context for the rest of the app. You would therefore only be able to access it during initialisation, which means you couldn't do it inside a setTimeout and get someone else's session by accident:
<script>
import * as app from '@sapper/app';
// this works...
const store = app.session();
// but this would fail
setTimeout(() => {
const store = app.session();
});
</script>
(app.session uses getContext under the hood.)
Implemented on current master, alongside #554 which makes it much harder to accidentally keep logged-in state visible after a client-side logout
Most helpful comment
Just realised this doesn't actually work. If
storeis just something exported by the app, there's no way to prevent leakage.Instead, it needs to be tied to rendering, which means we need to use the context API. Sapper needs to provide a top level component that sets the store as context for the rest of the app. You would therefore only be able to access it during initialisation, which means you couldn't do it inside a
setTimeoutand get someone else's session by accident:(
app.sessionusesgetContextunder the hood.)