Removes a module and all of its dependents from the require cache, so that subsequent requires of that module or any of its dependents will return new copies.
Useful for implementing a hot-reloading environment for Node.js programs in watch mode.
e.g. iterating on a static site generator that uses server side rendered React components for templating.
npm install invalidate-module
Start the module dependencies tracking by requiring invalidate-module
.
const invalidate = require('invalidate-module');
Call invalidate()
with the absolute path of a module to remove it and its
dependents from require.cache
.
invalidate(require.resolve('./my-module'));
Note that you must provide the absolute path of the module, so use something
like require.resolve()
or path.resolve()
.
Now the next time you call require('./my-module')
, it will return a new copy
of ./my-module
instead of a cached copy.
Example when used with a watcher like chokidar:
// watch.js
const chokidar = require('chokidar');
const invalidate = require('invalidate-module');
const path = require('path');
const watcher = chokidar.watch('*.js', { ignoreInitial: true });
require('./a');
watcher.on('all', (event, filename) => {
invalidate(path.resolve(filename));
require('./a');
});
// a.js
require('./b');
console.log('this is module a');
// b.js
console.log('this is module b');
Running watch.js
will call require('./a')
which prints:
this is module b
this is module a
If you make this change to a.js
and save:
// a.js
require('./b');
console.log('this is module a, version 2');
The watcher callback will fire and invalidate a.js
so that require('./a')
loads the new version and this gets logged:
this is module a version 2
Because b.js
is still in require.cache
, the require('./b')
does nothing.
If you make this change to b.js
and save:
// b.js
console.log('this is module b version 2');
b.js
and its dependent a.js
will be invalidated and re-running
require('./a')
in the watch callback will log:
this is module b v2
this is module a v2
At the time of requiring this module, node's require()
is monkey-patched so
that subsequent calls will add the caller module and the required module to a
graph. When you call invalidate()
on a module, it deletes the module from
require.cache
and then it uses the graph to get the module's dependents and
deletes them from require.cache
as well.
Running with env vars DEBUG=invalidate-module
will log the modules that are
deleted from require.cache
.
- My blog post on this subject.
- node-hot-reloading-boilerplate