Skip to content

Instantly share code, notes, and snippets.

@cpojer
Last active April 9, 2024 21:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • 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?

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