vite-plugins icon indicating copy to clipboard operation
vite-plugins copied to clipboard

HMR: use environment API to replace ssrLoadModule

Open lovetingyuan opened this issue 6 months ago • 5 comments

// appModule = await server.ssrLoadModule(entry)
appModule = await server.environments.ssr.runner.import(entry);

The main issue is that ssrLoadModule causes hot updates to fail. Since Hono runs in a Node.js environment, deep submodule imports cannot be collected by Vite's moduleGraph, leading to hot updates not taking effect. (This is my guess, but the problem genuinely exists). We could consider replacing it with the environment API: https://vite.dev/guide/api-environment-frameworks.html#environments-and-frameworks I've tested this with Vite 7, and it works, even though the entire Hono application is re-run. However, that's still better than hot updates not working at all.


Hono does not update when duplicate routes are registered; instead, it ignores them. This prevents the use of import.meta.hot.accept for fine-grained HMR. related: https://github.com/honojs/hono/issues/4147, https://github.com/honojs/hono/issues/3817

lovetingyuan avatar Jun 30 '25 07:06 lovetingyuan

related: https://github.com/honojs/vite-plugins/issues/124

@hono/vite-dev-server v0.20.0

lovetingyuan avatar Jun 30 '25 07:06 lovetingyuan

Thanks. I'll work on it.

yusukebe avatar Jun 30 '25 10:06 yusukebe

@lovetingyuan

Hono does not update when duplicate routes are registered; instead, it ignores them. This prevents the use of import.meta.hot.accept for fine-grained HMR.

I would like to understand your method for enabling fine-grained HMR for Hono. For example, like the flow below (I'm not sure if this is correct or not):

  • If /a is updated, only routes (handlers) registered for /a will be updated.
  • The routes (handlers) not related to /a will not be updated.

yusukebe avatar Jun 30 '25 21:06 yusukebe

Yes. In simple terms, it's like this: we assume the user places each different route into a separate module.

app.get('/api/foo', getHandler)
app.post('/api/foo', postHandler)
  • In the simple case, if the user modifies the handler's implementation or adds a new routing method, Vite will re-execute this module during HMR. If Hono supported route updates, re-executing this module could achieve the hot update effect (however, Hono currently appends new routes using an array, and due to the principle of closest match, previously registered routes will not use the new handler).
  • A more complex scenario is when the user deletes previous routes or changes the path of a route. The ideal way to handle this is to first unload or remove the original route, and then execute the new module. (This is a more unified and standard approach. For a good development experience, some compilation methods might be needed to achieve this, such as automatically injecting import.meta.hot related code, but some conventions might be required to identify which modules are route handlers).

Hot Module Replacement (HMR) is relatively mature in frontend development because frontend frameworks are component-based, with each component being a module, ultimately forming a tree structure. These characteristics make it easy for tools to inject HMR code. In contrast, implementing HMR on the server side does present some challenges, especially without good engineering conventions.

lovetingyuan avatar Jul 01 '25 02:07 lovetingyuan

Hi @lovetingyuan @JacobNWolf

Regarding server-side HMR, can you provide a minimal project/code with HMR? It's better not to use Hono, but you can use only a plain app like export default { fetch: () => new Response('Hi') }. I want to imagine the mechanism of server-side HMR before reviewing https://github.com/honojs/hono/pull/4430

yusukebe avatar Oct 03 '25 09:10 yusukebe