Prior to ES6 modules, it was (I'm told by other Stack answers) easy to force a JS script to be reloaded, by deleting its require
cache:
delete require.cache[require.resolve('./mymodule.js')]
However, I can't find an equivalent for ES6 modules loaded via import
.
That might be enough to make this question clear, but just in case, here's a simplified version of the code. What I have is a node server running something like:
-- look.mjs --
var look = function(user) { console.log(user + " looks arond.") }
export { look };
-- parser.mjs --
import { look } from './look.mjs';
function parse(user, str) {
if (str == "look") return look(user);
}
What I want is to be able to manually change the look.mjs file (e.g. to fix a misspelled word), trigger a function that causes look.mjs to be reimported during runtime, such that parse() returns the new value without having to restart the node server.
I tried changing to dynamic import, like this:
-- parser.mjs --
function parse(user, str) {
if (str == "look") {
import('./look.mjs').then(m => m.look(user))
}
}
This doesn't work either. (I mean, it does, but it doesn't reload look.mjs each time it's called, just on the first time) And I'd prefer to keep using static imports if possible.
Also, in case this is not clear, this is all server side. I'm not trying to pass a new module to the client, just get one node module to reload another node module.
Prior to ES6 modules, it was (I'm told by other Stack answers) easy to force a JS script to be reloaded, by deleting its require
cache:
delete require.cache[require.resolve('./mymodule.js')]
However, I can't find an equivalent for ES6 modules loaded via import
.
That might be enough to make this question clear, but just in case, here's a simplified version of the code. What I have is a node server running something like:
-- look.mjs --
var look = function(user) { console.log(user + " looks arond.") }
export { look };
-- parser.mjs --
import { look } from './look.mjs';
function parse(user, str) {
if (str == "look") return look(user);
}
What I want is to be able to manually change the look.mjs file (e.g. to fix a misspelled word), trigger a function that causes look.mjs to be reimported during runtime, such that parse() returns the new value without having to restart the node server.
I tried changing to dynamic import, like this:
-- parser.mjs --
function parse(user, str) {
if (str == "look") {
import('./look.mjs').then(m => m.look(user))
}
}
This doesn't work either. (I mean, it does, but it doesn't reload look.mjs each time it's called, just on the first time) And I'd prefer to keep using static imports if possible.
Also, in case this is not clear, this is all server side. I'm not trying to pass a new module to the client, just get one node module to reload another node module.
Share Improve this question edited Apr 22, 2020 at 22:43 DevOfZot asked Apr 22, 2020 at 22:21 DevOfZotDevOfZot 1,3921 gold badge13 silver badges26 bronze badges 1-
Node's
import
does not use the samerequire.cache
. I'm going to take a guess that it leans heavily on v8 internals for the new import code so cache expiry might not be exposed. – Matt Commented Apr 22, 2020 at 23:20
3 Answers
Reset to default 1You could try using nodemon to dynamically refresh when you make code changes
https://www.npmjs./package/nodemon
I agree with @tarek-salem that it's better to use vm
library. But there is another way to solve your problem.
There is no way to clear the dynamic import cache which you use in question (btw there is a way to clear the mon import cache because require
and mon import
has the same cache and the dynamic import
has its own cache). But you can use require instead of dynamic import. To do it first create require in parser.mjs
import Module from "module";
const require = Module.createRequire(import.meta.url);
Then you have 2 options:
Easier: convert
look.mjs
into monjs format (rename itlook.cjs
and usemodule.exports
).If want to make it possible to either
import
ANDrequire
look.mjs you should create the npm package with package.json{ "main": "./look.cjs", "type": "monjs" }
In this case in parser.mjs
you will be able to use require('look')
and in other files import('look')
or import * as look from 'look'
.
I don't know what the reason behind doing this, I think this is not safe to change the context of modules at runtime and cause unexpected behaviors and this is one of the reasons that Deno came to.
If you want to run some code evaluation at runtime you can use something like this using vm: https://nodejs/dist/latest-v16.x/docs/api/vm.html