Removing a module from the cache

# Isiah Meadows (6 years ago)

I could seriously use the ability to remove, relative to a module, a loaded module from the cache.

  • In my test runner, I don't want to have to append a random query just to reload all the test files in watch mode.
  • I was at one point running an experiment to try to use JS tagged templates as a template engine of sorts, but I can't really use ES modules because I need the ability to drop them from cache and re-import them manually.

I do not require any new syntax (it can just be a built-in exposed to hosts and maybe by hosts like Node), but I would like such a hook exposed.

This won't require much in the spec, but it will require three main spec changes:

  • A new per-realm specifier blacklist (like maybe realm.[[Reload]]) added.
  • The third requirement in HostResolveImportedModule 1 altered to not require idempotence when the specifier is in the current realm's [[Reload]] list.
  • All callees to HostResolveImportedModule changed to also remove the specifier from the current realm's [[Reload]] list if the operation completed normally.

Isiah Meadows contact at isiahmeadows.com, www.isiahmeadows.com

# kai zhu (6 years ago)

i don’t feel your use-case is a valid one. i've played with many crazy hot-module loading-techniques in my 7 years as a python-dev, and afterwards, first year as js-dev. reflecting on all that time spent, what have i learned? that for anything besides contrived toy-cases, i never trusted the modules would hot-load correctly, with properly resolved dependencies (especially inter-module class-inheritances, which was a factor why i'm hostile to inheritance-based design-patterns in dynamics-languages). in practice i always ended up restarting the entire app/test-runner after file-updates due to paranoia, and there was alot of loader-related tech-debt i should have deleted years earlier, but didn’t due to sentimental value.

the only valid use-case for hot-loading modified-modules is during bootstrap-phase (with minimal integration-worries about module-dependency issues), so you can insert instrumentation-code for test-coverage like this real-world example [1].

[1] bootstrap to load modified-modules with instrumentation-code for test-coverage kaizhu256/node-istanbul-lite/blob/2018.4.25/lib.istanbul.js#L2765, kaizhu256/node-istanbul-lite/blob/2018.4.25/lib.istanbul.js#L2765

kai zhu kaizhu256 at gmail.com

# Isiah Meadows (6 years ago)

First, I'm reconsidering this approach as per a discussion on #tc39 IRC, and plan to come up with a CommonJS prototype first before actually developing a proposal. Most likely, it won't actually involve mutating the graph, but something closer to Erlang's, where different versions of modules might coexist for different views of the world.

Second, there are ways around those issues you listed:

  1. If you stick with immutability, you can achieve something similar to what you'd get with Erlang or Elixir. You generally have to code for hot reloading, simply because it ruins the assumption you have full local control over the runtime's world.
  2. I've personally had to resort to restarting everything, but for me, it's not paranoia, but actual things breaking.
  3. Almost nobody outside OTP circles seem to correctly account for data and module dependencies. When a module changes, you have to also reload everything that imports it, so things actually work. You still can have implicit dependencies from arguments, but those are less common, and they almost never show up in object-oriented code bases (where things are typically directly imported).

But anyways, I'm letting this mailing list proposal die here while I figure out how best to come up with something truly compelling.


Isiah Meadows contact at isiahmeadows.com, www.isiahmeadows.com