最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I reload an ES6 module at runtime? - Stack Overflow

programmeradmin1浏览0评论

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 same require.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
Add a ment  | 

3 Answers 3

Reset to default 1

You 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:

  1. Easier: convert look.mjs into monjs format (rename it look.cjs and use module.exports).

  2. If want to make it possible to either import AND require 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

发布评论

评论列表(0)

  1. 暂无评论