Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion doc/api/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,14 @@ changes:
* `options` {Object}
* `load` {Function|undefined} See [load hook][]. **Default:** `undefined`.
* `resolve` {Function|undefined} See [resolve hook][]. **Default:** `undefined`.
* Returns: {Object} An object with the following property:
* `deregister()` {Function} Remove the registered hooks so that they are no
longer called. Hooks are otherwise retained for the lifetime of the running
process.

Register [hooks][] that customize Node.js module resolution and loading behavior.
See [Customization hooks][].
See [Customization hooks][]. The returned object can be used to
[deregister the hooks][deregistration of synchronous customization hooks].

### `module.stripTypeScriptTypes(code[, options])`

Expand Down Expand Up @@ -800,6 +805,63 @@ hook to signal that the chain is intentionally ending at your hook.
If a hook should be applied when loading other hook modules, the other hook
modules should be loaded after the hook is registered.

#### Deregistration of synchronous customization hooks

The object returned by `registerHooks()` has a `deregister()` method that can be
used to remove the hooks from the chain. Once `deregister()` is called, the hooks
will no longer be invoked during module resolution or loading.

This is currently only available for synchronous hooks registered via `registerHooks()`, not for asynchronous
hooks registered via `module.register()`.

```mjs
import { registerHooks } from 'node:module';

const hooks = registerHooks({
resolve(specifier, context, nextResolve) {
console.log('resolve hook called for', specifier);
return nextResolve(specifier, context);
},
load(url, context, nextLoad) {
return nextLoad(url, context);
},
});

// At this point, the hooks are active and will be called for
// any subsequent import() or require() calls.
await import('./my-module.mjs');

// Later, remove the hooks from the chain.
hooks.deregister();

// Subsequent loads will no longer trigger the hooks.
await import('./another-module.mjs');
```

```cjs
const { registerHooks } = require('node:module');

const hooks = registerHooks({
resolve(specifier, context, nextResolve) {
console.log('resolve hook called for', specifier);
return nextResolve(specifier, context);
},
load(url, context, nextLoad) {
return nextLoad(url, context);
},
});

// At this point, the hooks are active and will be called for
// any subsequent require() calls.
require('./my-module.cjs');

// Later, remove the hooks from the chain.
hooks.deregister();

// Subsequent loads will no longer trigger the hooks.
require('./another-module.cjs');
```

#### Hook functions accepted by `module.registerHooks()`

<!-- YAML
Expand Down Expand Up @@ -2031,6 +2093,7 @@ returned object contains the following keys:
[asynchronous `resolve` hook]: #asynchronous-resolvespecifier-context-nextresolve
[asynchronous hook functions]: #asynchronous-hooks-accepted-by-moduleregister
[caveats of asynchronous customization hooks]: #caveats-of-asynchronous-customization-hooks
[deregistration of synchronous customization hooks]: #deregistration-of-synchronous-customization-hooks
[hooks]: #customization-hooks
[load hook]: #synchronous-loadurl-context-nextload
[module compile cache]: #module-compile-cache
Expand Down
Loading