Implementing safe & secure file-based stores #9878
Replies: 7 comments 14 replies
-
@Rich-Harris @dummdidumm this solves this issue #5231 EDIT |
Beta Was this translation helpful? Give feedback.
-
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. |
Beta Was this translation helpful? Give feedback.
-
[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 = 100 If 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! |
Beta Was this translation helpful? Give feedback.
-
[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, |
Beta Was this translation helpful? Give feedback.
-
@AlbertMarashi Not sure if you're familiar with NodeJS' |
Beta Was this translation helpful? Give feedback.
-
I've implemented a prototype of this system using But because |
Beta Was this translation helpful? Give feedback.
-
Please see this new proposal: |
Beta Was this translation helpful? Give feedback.
-
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
load
functions in SvelteKit)This creates a few problems
Context
s or declare them globally in root layouts, and include them in theapp.d.ts
PageData
to ensure they are accurately typed, if we want to access them via the$page
store.context
of 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
import
ing themtypescript
/javascript
files 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 inVite
and can be adapted see: ssrTransform.ts)Pseudocode implementation
This would be the located somewhere in the respond.js file
How it works
universal_writable.ts
Using it would work like so:
user_store.ts
+layout.ts
+page.svelte
I think this solution would significantly improve the experience of developing with svelte, reduce the learning curve, and provide clean and ergonomic access to stores.
Beta Was this translation helpful? Give feedback.
All reactions