Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pygy/esm-reload
Reload an ES module and its dependencies
https://github.com/pygy/esm-reload
Last synced: 25 days ago
JSON representation
Reload an ES module and its dependencies
- Host: GitHub
- URL: https://github.com/pygy/esm-reload
- Owner: pygy
- License: isc
- Created: 2024-01-18T14:47:06.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2024-01-18T23:45:35.000Z (10 months ago)
- Last Synced: 2024-10-06T10:04:56.187Z (about 1 month ago)
- Language: JavaScript
- Homepage:
- Size: 13.7 KB
- Stars: 5
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ES module reload
This module lets you reload an ES module and its dependencies in `Node.js`. It does so by adding a [module resolution hook](https://nodejs.org/api/module.html#resolvespecifier-context-nextresolve).
## Background
Per spec, ES modules are cached the first time they are imported, and subsequent import statements return the same object.
```JS
import {assert} from 'node:assert/strict'const m1 = await import('./my-module.js')
const m2 = await import('./my-module.js')assert.equal(m1, m2) // passes
```This is desirable in most scenarios, but you can sometimes want to instantiate a module several times. For example, you may want to test a module that branches at load time depending on its environment. To some extent, that can be achieved by tacking a query string at the end of the `import` specifier:
```JS
import {assert} from 'node:assert/strict'const m1 = await import('./my-module.js?dev')
process.env.NODE_ENV='production'
const m2 = await import('./my-module.js?prod')assert.notEqual(mDev, mProd) // passes
```However, this doesn't work transitively. `./my-module.js?prod` will import the dependencies that were cached when `./my-module.js?dev` was loaded.
If you want to load a module multpile times from scratch with its dependencies you can use this module.
## Usage:
The resolver hook gives a special meaning to `?instance=...` and `?reload` query strings.
If you want to retrieve a specific instance, use the former with an identifier of your choice.
```JS
import "esm-reload" // this registers the hookconst mDev = await import("./myModule.js?instance=dev")
process.env.NODE_ENV='production'
const mProd = await import("./myModule.js?instance=prod")
const mDev2 = await import("./myModule.js?instance=dev")assert.equal(mDev, mDev2) // passes
assert.notEqual(mDev, mProd) // passes
```If you just want a fresh instance you can use `?reload`
```JS
const mReloaded = await import("./myModule.js?reload")
assert.notEqual(mDev, mReloaded) // passes
assert.notEqual(mProd, mReloaded) // passes// ?reload is "magic"
const mReloaded2 = await import("./myModule.js?reload")
assert.notEqual(mReloaded, mReloaded2) // passes
```In both cases, instances come with a fresh set of dependencies (except for the builtin `node:xxx` modules that don't support query strings at all).
### With dependencies
Suppose these files:
```JS
// foo.js
export {x} from "./bar.js"// bar.js
export const x = {}
```We can then do
```JS
import "esm-reload"const foo1 = await import("./foo.js?instance=1")
const bar1 = await import("./bar.js?instance=1")const foo2 = await import("./foo.js?instance=2")
const bar2 = await import("./bar.js?instance=2")assert.equal(foo1.x, bar1.x)
assert.equal(foo2.x, bar1.x)assert.notEqual(bar1.x, bar2.x)
```## Credit:
The hook was originally written by Marcel Laverdet([@laverdet](https://github.com/laverdet)) then tweaked, tested and documented by yours truly.
## License
ISC