sveltejs/svelte-loader

Svelte 3 HMR

rixo opened this issue ยท 12 comments

rixo commented

I've seen HMR support is on its way: sveltejs/svelte#2377

But I couldn't wait to play with svelte-native, and no HMR is really a bummer there. Because the smallest change triggers a full relaunch of the app on the device, losing the page you were working on in the process...

So I hacked myself together a preliminary HMR for svelte3 & svelte-native.

It's more experiment than anything. It mainly only supports restoring state by public (exported) props, and it's not very stable.

But it already proved useful to me so I was thinking of sharing it, as a temporary solution for other impatient people. Maybe it could also be useful to work around HMR support for svelte-native since, as I have found, it presents its own challenges.

So I wanted to see if you had any thought to share on this. Like maybe how it goes with your projected timing, or anything ?

Also, I've got a question to ask. My changes also impacted the svelte-dev-helper project. For simpler logistics, I was thinking of merging svelte-dev-helper in my fork of svelte-loader. Is there a specific reason why it's not already the case? The two projects seem pretty tightly coupled to me, is there something I missed?

svelte-dev-helper needs to be separate.
Because it also powers other loaders apart from webpack.
Right now it also powers Parcel.

Please share your implementation, we might all learn from it.

We are still missing "blessed" api methods to support HMR.
Maybe @Rich-Harris will get round to inject_state and capture_state soon ๐Ÿ˜„

rixo commented

Hey! I finally had some time to tidy this all up a bit.

So, here are my forked versions of svelte-loader and svelte-dev-helper, with experimental HMR.

And here's a demo svelte3 app, and another one for svelte-native.

As I said, HMR support is very crude since it does only preserve public props state. Still, it is a satisfying experience. At least for me.

To be honest, I didn't test it extensively by any mean. What I'm really focused on at the moment is making it work with svelte-native.

And it does work in svelte-native! Somewhat... Support for HMR update of root NS/SN Page component proved quite tricky and is nowhere near done. I'm still trying to see is I can squeeze something out of it. Despite this, it's already a nice time saver :)

Anyway, I hope this can be entertaining, maybe even useful, to others. I'd be happy to ear any feedback.

rixo commented

@ekhaled So, do you think we should work that into a PR? Did you have some time to look at it?

rixo commented

So... This has become a little bit more than experimental by now.

I think it is now feature complete or close to it. Thanks to recently merged $inject_state, it even supports preservation of local state (by using vars from compiler output because $capture_state won't let capture local state for now).

I run some e2e tests on the HMR support and it seems to work pretty well, but I can't really tell because I haven't got much feedback from other users. That is, there isn't really a good place where this feedback could happen currently...

In my opinion, HMR support should not wait for dedicated hooks to be implemented in Svelte. Exposing the experimental implementation to wider usage would allow to identify issues that could otherwise be overlooked in a purely theoretical discussion.

I believe it's best to gather as much information as possible before making a complete proposal for the hooks that are really needed for HMR. This would need that people know about it, use it, and have a place to report feedback though.

So, what do you think? Would you be interested in working to merge my implementation with emulated dev hooks in this repository? I'm just asking for better organisation, I can totally understand if you don't want to accept hackish code.

cc @ekhaled

Any news regarding HMR support for Svelte 3? Just tried setting it up using the latest version of svelte-loader and realized, that it throws errors trying to proxy the method get in svelte-dev/lib/proxy.js:62

$ TypeError: undefined is not an object (evaluating 'self.proxyTarget[method].apply') โ€” proxy.js:62

The documentation gives the impression that HMR generally works, but that seems to be the case only for Svelte 2 (?).

@dweidner It works for Rollup, there is a sample template and related PRs and Issues on the Roadmap: https://github.com/sveltejs/svelte/projects/5

Doesn't work with webpack, importing even the simplest of components is causing TypeError: "header.$$ is undefined". header$$ being an example component. Disabling hot reloading in webpack-dev-server makes the error go away.

Lack of hot reloading is a major PITA during the development, are there any news on this front?

Going by the issue referenced in the roadmap (#107) last (failed) commit was on the 29th of July. svelte-loader-hotdoesn't seem to work with webpack either (rixo/svelte-loader-hot#4).

@boojum same here. TypeError: Cannot read property 'fragment' of undefined
can't find somecomponent.$$.fragment

@jaikme I'm afraid that I can't help here - between this and the issues with hydration I decided to use different approach to my frontend.

rixo commented

svelte-loader-hot is supposed to work with Webpack (and rollup-plugin-svelte-hot with Rollup -- check the readme of svelte-hmr for more info). In any case, you need the dev option of the Svelte (hot) plugin to be set to true, or you get the aforementioned error.

rixo commented

The experiment that was the object of this issue has now matured into svelte-hmr, that is currently powering Svelte HMR (who said naming was hard?) in plugins for several tools.

Moving HMR into the compiler is now a relatively agreed upon goal, but I don't foresee it being fulfilled in the immediate future. Part of the reasons is some hard technical challenges -- a notable one is that HMR today is very coupled to each specific dev tool, and Svelte wants to avoid favoring one specific tool (there are now way more diverse HMR enabled tooling than when I first started this discussion, too).

The main slower though is that the feature currently exists and works well. It wouldn't work any better by being part of the core (because required supporting features have already been added to the core), and everybody involved is committed to keep it working. There isn't a pressing unavoidable pain to alleviate here anymore...

So, at the time of writing this, efforts are rather focused both on making the feature more available to everybody in the different tools plugins, including officially supported ones, and building solid test suites to back a serene future claim of official support.

The discussion this issue was meant for is now happening at several other places, and has ramified into more targeted and actionable goals. I don't think there's anything more to be added here, and so closing.

I'm pretty satisfied of the ground we've covered since then, I must say. (Don't nobody dare dropping a shortsighted "stuck in development hell" comment, please!)

For now, the best place to get the latest news about Svelte HMR status remains svelte-hmr's README. (Best place for HMR-specific feedback too!).

svelte-loader now uses svelte-hmr in master which we plan to release as 3.0.0 later