Implementing safe & secure file-based stores #9878
Replies: 6 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.
-
Hi everyone,
I have implemented a Draft PR prototype that implements request-level store isolation during server-side rendering using node's
AsyncLocalStorage
functionality which enables the ability to provide different global contexts to code running within isolated async functions (as is done in the server response generation code)#12215
Would love to get your feedback and finally solve this important issue
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 #4339 and #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