Skip to content
Open
Show file tree
Hide file tree
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
51 changes: 51 additions & 0 deletions doc/api/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,57 @@ const require = createRequire(import.meta.url);
const siblingModule = require('./sibling-module');
```

### `module.clearCache(specifier[, options])`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.1 - Active development

* `specifier` {string|URL} The module specifier or URL to resolve. The resolved URL/filename
is cleared from the load cache; the specifier (with `parentURL` and `importAttributes`)
is cleared from the resolve cache.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it more -what's the point of clearing the resolve cache? For the purpose of HMR, I think clearing the load cache is usually enough, and many user-land solutions never seem to care about the resolve cache. Even in the examples below, it doesn't demonstrate clearing the resolve cache. I think it's better to either split them into two APIs, or add an option that allows users to control which one to clear.

* `options` {Object}
* `mode` {string} Which caches to clear. Supported values are `'all'`, `'commonjs'`, and `'module'`.
Copy link
Member

@joyeecheung joyeecheung Feb 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this isn't a very good choice as an option. For resolution, 'commonjs' and 'module' is not what distinguish how a module should be resolved - it's the conditions: i.e. require or import (and addon, module-sync, node etc). What can be cleared are the "require cache" and "import cache", not "commonjs cache" and "esm cache", because require(esm) and import(cjs) can happen, and they can happen in both types of modules (CommonJS can import(), and ESM can require() via createRequire). If a user wants to clear the cache for require(esm) or import(cjs), the current option is not exactly clear about which one they should choose. Using condition instead of this convoluted mode would fit a lot better for the resolution case.

There's also the question of what happens when the same x.js has been loaded through: import('./x.js?t=1'), import('./x.js?t=2'), require('./x'), I think it's worth either documenting them as quirks in the docs, or just change the behavior to always clear everything for loading because it currently reads like a can of worms:

  1. If x is ESM, but only the ESM cache for 'x.js' is cleared, still none of them will see a re-execution when they happen again. For a third-party tool, they have to intercept all requests from users that resolve to this x.js to make sure all of them get refreshed.
  2. If x is ESM, and only the CJS cache is cleared, then none of these will see a re-execution when they happen again.
  3. If x is CJS, and only the CJS cache is cleared, the imports won't see a re-execution but require will, and you can end up with two copies of the same global state in the graph in conflict with each other
  4. If x is CJS, and only the ESM cache is cleared, then the require won't see a re-execution but import will, and you can end up with two copies of the same global state in the graph in conflict with each other

The latter two again re-introduces the dual package hazard. IMO for loading cache, it's better to always just clear them all and don't even leave an option for partial clears unless anyone specifically ask for them. Also, while 2 and 4 seems silly, the current way of mixing the resolution with loading in the API can very easily trick you into them. Splitting the two APIs helps avoid unintentional partial clears.

**Default:** `'all'`.
* `parentURL` {string|URL} The parent URL used to resolve non-URL specifiers.
For CommonJS, pass `pathToFileURL(__filename)`. For ES modules, pass `import.meta.url`.
* `importAttributes` {Object} Import attributes for ESM resolution.
* Returns: {Object} An object with `{ commonjs: boolean, module: boolean }` indicating whether entries
were removed from each cache.

Clears the CommonJS `require` cache and/or the ESM module cache for a module. This enables
reload patterns similar to deleting from `require.cache` in CommonJS, and is useful for HMR.
When `mode` is `'all'`, resolution failures for one module system do not throw; check the
returned flags to see what was cleared.
This also clears resolution cache entries for that specifier. Clearing a module does not clear
cached entries for its dependencies, and other specifiers that resolve to the same target may
remain.
When a `file:` URL is resolved, cached module jobs for the same file path are cleared even if
they differ by search or hash.

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

const url = new URL('./mod.mjs', import.meta.url);
await import(url.href);

clearCache(url);
await import(url.href); // re-executes the module
```

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

const file = path.join(__dirname, 'mod.js');
require(file);

clearCache(file);
require(file); // re-executes the module
```

### `module.findPackageJSON(specifier[, base])`

<!-- YAML
Expand Down
Loading
Loading