alloc/saus

Faster reloading of isolated modules

Opened this issue · 2 comments

Currently, all isolated modules are reloaded between page requests. Additionally, this reloading does not take place until the next request comes in.

  • We should reload eagerly (after each request, instead of before)
  • We should reload only the modules that are stateful
  • We need to build a module graph (really just the importers of each module) so we can reload selectively

The first solution that comes to mind is import.meta.hot (Vite's HMR API). This is a flexible solution, as the user (and even plugins) can control how a module is reloaded, instead of only switching reload on/off. But it's also more verbose than, say, adding /* @hot */ at the top of the module, or managing a list of stateful modules from your Saus config (which I'd like to avoid, since the list can get out of sync).

I don't think we'll need to implement the entirety of Vite's HMR API. Just the basics for now.

We should reload only the modules that are stateful

  • When compiling ESM in current (unreleased) version of Saus, we already avoid top-level dependency destructuring if the dependency has mutable exports (eg: export let), so using export let for "global state" is highly recommended if you want to reload as few modules as possible between requests (even if you never actually update the export let value).

  • Assume a server module is stateful if…

    • it contains an export let or export var statement
    • it exports a new expression like new WeakMap() with an export const statement
    • it uses an imported value from a stateful module at its top-level

Functions that mutate global state

If a server module contains an exported function that mutates global state referenced from an outer scope (not from an argument), you should export it with export let to ensure the module is reloaded between requests. This is not necessary if the module in which this function exists is already stateful.

The first solution that comes to mind is import.meta.hot (Vite's HMR API).

Currently, "state modules" need special casing in the src/dev/hotReload module. This feature will let us avoid that.