esm-hmr icon indicating copy to clipboard operation
esm-hmr copied to clipboard

Further work & notes

Open laverdet opened this issue 9 months ago • 0 comments

I know this project is archived but I wanted to point out some additional work I've done in this space for hot reloading nodejs services: https://github.com/braidnetworks/dynohot

In particular I've explored and implemented support for top-level await, dynamic imports, promise-returning handlers, relinking of imported bindings, and refined the order in which handlers should run.

  • Top-level await doesn't add too much complexity and is generally handled by the host environment.
  • Handling hot reloadable dynamic imports without risk of deadlocking is, I believe, a fancy version of the halting problem. What I've found in practice is that dynamic imports tend to fall into two categories: lazy imports, and conditional imports. In both cases you can more or less treat them as static imports while reloading and have them participate in the ECMAScript cyclic module resolution algorithm for reloading purposes.
  • To that end, modules which participate in a module cycle as described in the specification cannot be accepted unless all members are also accepted. In my implementation I just warn you when you've accepted a cycle member and that it cannot be accepted.
  • All handlers should be able to return promises which will be awaited before continuing the reload or invoking other handlers in the same scope. This one is a no brainer and ensures resources are collected cleanly and exceptions are propagated correctly.
  • Live relinking of imported bindings feels like the way to go. Getting the implementation right is difficult but the developer experience is a lot better. One condition it does create is that any consumers of a self-accepted modules will suddenly have their imported bindings swapped out from under them without any notification channel.
  • accept handlers should be invoked in the order they are defined, but dispose (and probably prune) handlers should be invoked in reverse order. When you get into the nitty gritty of cleaning up complex middleware this shakes out naturally in the same way C++ figured out RAII.
  • Oh yeah prune is definitely good to include. Vite got this one correct, and it has applications on the server side too.

Anyway that's a very abbreviated brain dump of the thoughts I had while building dynohot. Thanks for your work on this repo!

laverdet avatar Sep 29 '23 05:09 laverdet