vite-plugin-svelte: HMR breaks `context="module"` exports
Describe the bug
If you’ve exported a function using <script context="module">, HMR updates from that component causes other the exported function to no longer run from other components where it’s imported.
Reproduction
https://github.com/probablykasper/svelte-vite-context-module-exports-bug
npx degit probablykasper/svelte-vite-context-module-exports-bug svelte-vite-context-module-exports-bugcd svelte-vite-context-module-exports-bug && npm inpm run dev- Open the website and check that the
ShowandHidebuttons work - Trigger HMR in
Counter.svelte, for example by changing the<h3>tag - Now the
ShowandHidebuttons are broken
Logs
No response
System Info
System:
OS: macOS 10.15.7
CPU: (8) x64 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz
Memory: 1.21 GB / 32.00 GB
Shell: 3.2.2 - /usr/local/bin/fish
Binaries:
Node: 14.16.0 - /var/folders/44/3sxbyc2d6wg90mj1s7s59bnm0000gn/T/fnm_multishells/23267_1628209481847/bin/node
Yarn: 1.22.10 - /var/folders/44/3sxbyc2d6wg90mj1s7s59bnm0000gn/T/fnm_multishells/23267_1628209481847/bin/yarn
npm: 6.14.11 - /var/folders/44/3sxbyc2d6wg90mj1s7s59bnm0000gn/T/fnm_multishells/23267_1628209481847/bin/npm
Browsers:
Brave Browser: 92.1.27.108
Chrome: 92.0.4515.131
Firefox: 89.0.2
Safari: 14.1.2
npmPackages:
@sveltejs/vite-plugin-svelte: 1.0.0-next.15 => 1.0.0-next.15
svelte: ^3.42.1 => 3.42.1
vite: ^2.4.4 => 2.4.4
Severity
annoyance
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 16 (6 by maintainers)
Commits related to this issue
- fix: update svelte-hmr and enable partial accept to allow context=module updates, see issue #134 — committed to sveltejs/vite-plugin-svelte by dominikg 2 years ago
- fix: update svelte-hmr and enable partial accept (#440) * fix: update svelte-hmr and enable partial accept to allow context=module updates, see issue #134 * test: harden partialAccept test (#441) ... — committed to sveltejs/vite-plugin-svelte by dominikg 2 years ago
the fix for this (partial HMR) might have uncovered this. Can’t tell if this is a bug in v-p-s / svelte-hmr or a problem in your project.
Please file a new issue and provide a minimal reproduction. Ideally without routify in a clean vite+svelte project.
should be fixed in 1.0.6
@Sayyiditow Hi! For now, the best workaround you can have is probably to split
<script context=module>parts into their own.jsfile. I understand how this might not be practical in some situations, though.The fix is in progress. Vite 3 has added the experimental option we need to address this on our side. I’m reserving some time to add it to svelte-hmr in the coming days, and hopefully it can make its way into the Vite plugin soon after.
FYI the fix effect will be that any change to theEdit I was out of my mind when writing this 😅 . What I described was the solution we did not implement because too brutal. The actual fix that has just been done is that only consumers of named exports (from context=module) get invalidated when the source module changes. Consumers of only the default export (that is, the Svelte component) do not get updated. For HMR this is the equivalent to have the part in context=module in a separatecontext=modulepart will cause invalidation of the whole.svelteSFC (single file component), meaning HMR will recreate all consumers (importers) of the SFC. If any of those consumers is not a Svelte component (or otherwise “accepted” HMR module), this will cause a full reload. Changes to the rest of the SFC (that is the Svelte component proper) will have HMR as usual..jsfile – and this is the best than can be handled from within Svelte.broken code from repo above
App.svelte
Counter.svelte
what happens
When you edit
Counter.sveltethis results in a recompile and the js code is sent to the browser. svelte-hmr then “reapplies” that code and replaces all instances of Counter with new ones. The new Counters get a reference to a new instance of thevisiblestore, as can be witnessed when clicking once so that the browser shows “visible true”, and then editing Counter.svelte. It updates to “visible false”, because it shows the initial value of the new instance.The instance of App.svelte on the other hand remains unchanged and that imported the original instance of the visible store. So now you have 2 instances of the same store and of course updates to the one App.svelte has won’t propagate to the new Counter.
how to avoid it
Move the store to it’s own module to avoid recreating it on update
store.ts
App.svelte
Counter.svelte
Now the hmr update of Counter no longer creates a new instance of the visible store and you can enjoy hmr.
cc @rixo
This is a limitation of the current implementation and trying to also invalidate all Components that import from an hmr updated Components context=module could cause a big cascade effect.