kit
kit copied to clipboard
[HMR] setInterval calls keep stacking when a module is reloaded
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.
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.
Definitely related to #11932
Agreed it looks related. That issue has been open for some time now, so is there any ETA when it will be looked at?
For the reference, I'm using the following workaround to restart the whole server whenever any server-side code changes:
export default defineConfig({
plugins: [
sveltekit(),
{
name: 'restart on server change',
enforce: 'pre',
handleHotUpdate({ file, server }) {
if (file.includes('/server/') || file.endsWith('hooks.server.ts')) {
setImmediate(() => server.restart())
return []
}
},
},
],
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
},
})
Hopefully, with the new Environment API we'll have a proper server-side HMR functionality soon