orlov-vo / parcel-transformer-svelte

Parcel 2 transformer for Svelte 3
https://www.npmjs.com/package/parcel-transformer-svelte
MIT License
40 stars 18 forks source link

HMR duplicates module, doesn't replace #10

Open canadaduane opened 3 years ago

canadaduane commented 3 years ago

I'm seeing modified modules in the development server get appended instead of replaced. I believe the way Hot Module Reloading (HMR) should work is it should replace modified modules.

As an example of the problem, the red box test case app normally shows one red box:

image

But when I modify the source code to add the text "hi!" it does not replace the module, it appends it:

image

I expect to see just one red box when I add text above the box.

canadaduane commented 3 years ago

I believe we may be missing a uniqueKey in the transformation output. The VueTransformer (as an example of another implementation of a Transformer) has such a key here:

https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/vue/src/VueTransformer.js#L462

canadaduane commented 3 years ago

uniqueKey didn't seem to fix the issue. I'm also wondering if it's truly HMR, or if there is some other mechanism that reloads pages or modules?

orlov-vo commented 3 years ago

as workaround you can clean your app's target before init component:

import App from './App.svelte';

const target = document.getElementById('svelte-root')
target.innerHTML = ''
new App({ target })
SmileyChris commented 3 years ago

Even with that workaround, it is causing clicking a routed link to raise an exception until I refresh.

simonwiles commented 3 years ago

I seem to be getting a huge memory leak here too -- each time the app is hot-reloaded, the memory consumption increases 1-fold. Something is definitely wrong...

(Edit: while the workaround suggested by @orlov-vo works to clear the target element before the modules are rendered, it doesn't seem to clear them from the runtime, hence the issue @SmileyChris notes above and the memory leakage.)

orlov-vo commented 3 years ago

You can also try to use HMR-API for component disposing

import App from './App.svelte';

const target = document.getElementById('svelte-root')
const app = new App({ target });

if (module.hot) {
    module.hot.dispose(() => {
        app.$destroy()
    })
}