Repository navigation
Implementing safe & secure file-based stores #9878
Replies: 7 comments 14 replies
|
@Rich-Harris @dummdidumm this solves this issue #5231 EDIT |
|
I don't understand how this would safely determine which store instance belongs to which request, and how it would prevent memory leaks since the store is never unloaded. |
|
[outdated: the proposal was changed!] I still think there is an issue with this approach: At some point a copy of a store is neccesary. Copying is hard, because sometimes we need a reference to it, but sometimes a clone to it. Two examples (that I have stumbled upon) to show what I mean:
When storing/modifying an object with multiple sub-objects, a clone would be neccesary: // stores.js
export let settings = writable({sound: {volume: 100}})
// component.svelte
$settings.sound.volume = 100If a reference to the objects is passed here, the state will be globally shared.
I recently worked on a small i18n library based on JS objects. I used a placeholder proxy to get placeholders while it is loading a new language: let lang = writable(placeholderProxy)
let loadLanguage = code => lang.set(getLanguage(code))
console.assert(lang.this.property.doesnt.exist.but.the.proxy.fills.it.in)Cloning that would make that proxy break. And the other problem is references to other stores. For example, in my i18n library I have two connected stores: export let lang = writable({hello: 'Hello World'})
export let langCode = writable('en')
langCode.subscribe(code => lang.set(getLang(code)))Isolating those references seems pretty hard, and I think that the best solution is to give the users the choice. I'm implementing a small workaround library and using it on a few projects to get end-user experience, and I've come to the conclusion that the best way is to provide three options:
I thought about this the last few days and I think the mentioned edge cases can only be solved by either using VMs or giving the users this choice, but if you know how to fix those issues LMK! |
|
[outdated: the proposal was changed!] Also, correct me if I'm wrong but wouldn't this break with async requests? In a 100% sync context it should work, but if two requests get SSR'd at the same time, |
|
@AlbertMarashi Not sure if you're familiar with NodeJS' |
|
I've implemented a prototype of this system using But because |
|
Please see this new proposal: |

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Edit: Please see the following proposal
Proposal for Svelte 5: Universal Reactivity & Safe SSR Global State? svelte#12947
Old Approach
Current Issue
Using Stores in SvelteKit requires you to initialize them during a request entry (currently done via the
loadfunctions in SvelteKit)This creates a few problems
Contexts or declare them globally in root layouts, and include them in theapp.d.tsPageDatato ensure they are accurately typed, if we want to access them via the$pagestore.contextof Svelte ComponentsThis seems like the most complained about issue in SvelteKit, according to upvotes of Sharing a global variable across multiple requests is unsafe in SSR #4339 and Clarification on safely using stores in Sveltekit #6098
Proposed Solution
I propose a solution of creating a Safe Stores and safe variables by isolating the stores across requests, enabling file-based stores to exist, and additionally enabling normal typescript files to be able to import them.
Benefits
importing themtypescript/javascriptfiles to import stores, without side effectsModifications to svelte
Transforming build modules into async functions
Say we have the following code:
will be transformed into something that looks like this at compile/build-time (simplified):
This is done by parsing the compiled output, and walking the AST tree to find instances of
import/export& etc. (most of the code for this already exists inViteand can be adapted see: ssrTransform.ts)Pseudocode implementation
This would be the located somewhere in the respond.js file
How it works
universal_writable.tsUsing it would work like so:
user_store.ts+layout.ts+page.svelteI think this solution would significantly improve the experience of developing with svelte, reduce the learning curve, and provide clean and ergonomic access to stores.
All reactions