Skip to content

Instantly share code, notes, and snippets.

@cpojer
Last active July 23, 2024 13:49
Show Gist options
  • Save cpojer/b07a7b512f03c0b1692e35dfb94da90b to your computer and use it in GitHub Desktop.
Save cpojer/b07a7b512f03c0b1692e35dfb94da90b to your computer and use it in GitHub Desktop.
When using `vite-node` with http servers, any HMR update will crash the process because the port is in use. This code can be inserted at the top-level of your script to gracefully stop the previous server instance before starting the new one.
#!/usr/bin/env node_modules/.bin/vite-node --watch
// `vite-node` HMR handler for servers.
type TeardownCallback = () => Promise<void>;
type Listener = () => TeardownCallback;
declare global {
// eslint-disable-next-line no-var
var __HMR__: {
listeners: ReadonlyArray<Listener>;
teardownCallbacks: ReadonlyArray<TeardownCallback>;
};
}
const key = '__HMR__';
function register(listener: Listener) {
if (import.meta.hot) {
import.meta.hot.accept(async () => {
const hmr = global[key];
const teardownCallbacks = hmr.teardownCallbacks.map((fn) => fn());
hmr.teardownCallbacks = [];
await Promise.all(teardownCallbacks);
hmr.teardownCallbacks = hmr.listeners.map((listener) => listener());
hmr.listeners = [];
});
} else {
listener();
return;
}
if (!global[key]) {
const teardown = listener();
Object.defineProperty(global, key, {
value: {
listeners: [],
teardownCallbacks: [teardown],
},
});
} else {
global[key].listeners = [...global[key].listeners, listener];
}
}
register(() => {
httpServer.listen(port);
return () => new Promise((resolve) => httpServer.close(() => resolve()));
});
@paynecodes
Copy link

@cpojer I've been scouring the internet for something like this. How's this treating you in 2024?

@Eflyax
Copy link

Eflyax commented Jul 23, 2024

Not working for me. Variable import.meta is undefined in my code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment