stackblitz / core

Online IDE powered by Visual Studio Code ⚡️
https://stackblitz.com
MIT License
10.29k stars 914 forks source link

Persist changes on embedded instances (emit a save event or let us know the forked url) #1982

Open nimonian opened 2 years ago

nimonian commented 2 years ago

Embedding projects with the SDK is amazing, but persisting the users' changes is hard (perhaps intentionally, see additional context).

There are two different scenarios to think about:

With Id embedProjectId() At the moment, saving the same embed several times between refreshes just makes more and more forks. If we could get the url of the fork we could stick it in local storage or a database and restore it rather than reloading the template.

Without Id embedProject() We have the method getFsSnapshot() which would allow us to restore the users' changes, but there's no way to react when the user hits save because the iframe is cross origin.

Describe the solution you'd like

Either:

Describe alternatives you've considered

We can check the preview.getUrl() to figure out the id of the fork and work backwards. We can get a snapshot every few seconds rather than responding to save events.

Additional context

I've read some differing opinions on this, but ultimately, Stackblitz is an incredible editor and people will want to use it for various education projects etc. The with Id solution (forking) is understandably not popular because we're essentially using stackblitz as a storage bucket for people's work. But the snapshot solution seems pretty reasonable - we're responsible for saving and restoring their work, we just need to know when. The latter solution is also compatible with the embedded layout.

fvsch commented 1 year ago

At the moment, saving the same embed several times between refreshes just makes more and more forks.

Embeds are not supposed to create forks (while staying in the embed; there is a button to fork the project on StackBlitz). We fixed a couple bugs last year where this could happen on some user actions, so this should not be a problem anymore.

We have the method getFsSnapshot() which would allow us to restore the users' changes, but there's no way to react when the user hits save because the iframe is cross origin.

Just wanted to confirm that we don't currently send events to the parent page when a user or some other process modifies a file. The only solution is to regularly poll vm.getFsSnapshot().

We might be able to notify the vm of fs updates, but there could be performance implications and so far the demand for this has been low.

nimonian commented 1 year ago

Ideal would be to have the vm emit a "save" event

vm.onSave((event) => {
  // do stuff
})

which triggers when the user saves. We don't need anything else - just to know at what moment the user hits ctrl + s, then we can use vm.getFsSnapshot() or whatever else we want to do in reaction to the save event.

I wonder if using the iframe postMessage api would solve the performance issues? Presumably the embed already does stuff in response on the save event so posting 'save' as part of that handler hopefully wouldn't add any overhead.

Embeds are almost able to CRUD local file systems - we can load them from json, we can read the updated files but we just don't know when. A listenable save event feels like a no-brainer to me and completes the feature-set that embeds offer - without knowing when the user saves, I wonder why vm.getFsSnapshot() was implemented in the first place?