sveltejs / kit

web development, streamlined
https://svelte.dev/docs/kit
MIT License
18.7k stars 1.93k forks source link

[HMR] setInterval calls keep stacking when a module is reloaded #12618

Open majanojoel opened 2 months ago

majanojoel commented 2 months ago

Describe the bug

I have a function I would like to call periodically so I initialize a setInterval loop in interval.ts by importing handle in hooks.server.ts. The return value from setInterval is exported as handle. The bug is that whenever the console.log is updated, the output in the console shows there are two setInterval loops running. This output keeps stacking as more changes are made and more HMR updates are triggered. For example, if you update the runAsync(1) call to runAsync(2) you will see the following console output:

tick 1
tick 2
tick 1
tick 2
tick 1
tick 2

I tried using import.meta.hot in interval.ts with a dispose following accept(), as well as others like invalidate and on('vite:beforeUpdate', ...) but this behavior persisted or at best the first loop was the only one that kept running after HMR updates.

This is all running using npm run dev. Am I doing something wrong with import.meta.hot or is there another way to cleanup the previous loop?

Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-2xzaqm?file=src%2Flib%2Fserver%2Finterval.ts

Logs

No error logs were produced

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 18.20.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/adapter-auto: ^3.0.0 => 3.2.4 
    @sveltejs/kit: ^2.0.0 => 2.5.24 
    @sveltejs/vite-plugin-svelte: ^3.0.0 => 3.1.2 
    svelte: ^4.2.7 => 4.2.19 
    vite: ^5.0.3 => 5.4.2

Severity

serious, but I can work around it

Additional Information

Reproduced using the SvelteKit template on StackBlitz.

atuleu commented 2 months ago

Also come up with the same issue. It seems hooks.server.ts is never called with import.meta.hot, therefore one could not do:

let interval = undefined;

if (dev) {
  interval = setInterval(()=>{
    console.log('pong');
  },1000);
}

if (import.meta.hot) {
   import.meta.hot.dispose(()=> {
   if ( interval !== undefined ) {
     clearInterval(interval);
     interval = undefined;
   }
}

Which seems from svelte-hmr the way to go for disposing resource on HMR events.

atuleu commented 2 months ago

Definitely related to #11932

majanojoel commented 2 months ago

Agreed it looks related. That issue has been open for some time now, so is there any ETA when it will be looked at?