简体   繁体   English

如何在运行时重新加载 ES6 模块?

[英]How can I reload an ES6 module at runtime?

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:在 ES6 模块之前,通过删除其require缓存,很容易强制重新加载 JS 脚本(其他 Stack 答案告诉我):

delete require.cache[require.resolve('./mymodule.js')]

However, I can't find an equivalent for ES6 modules loaded via import .但是,我找不到通过import加载的 ES6 模块的等效项。

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 (eg 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.我想要的是能够手动更改 look.mjs 文件(例如修复拼写错误的单词),触发一个导致 look.mjs 在运行时重新导入的函数,这样 parse() 就可以返回新值而不必重启节点服务器。

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. (我的意思是,它确实如此,但它不会在每次调用时重新加载 look.mjs,只是在第一次调用时)而且我希望尽可能继续使用静态导入。

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.我不是要将新模块传递给客户端,只是让一个节点模块重新加载另一个节点模块。

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.我不知道这样做的原因是什么,我认为在运行时更改模块的上下文并导致意外行为是不安全的,这也是 Deno 出现的原因之一。

If you want to run some code evaluation at runtime you can use something like this using vm: https://nodejs.org/dist/latest-v16.x/docs/api/vm.html如果你想在运行时运行一些代码评估,你可以使用 vm 使用类似的东西: https://nodejs.org/dist/latest-v16.x/docs/api/vm.html

You could try using nodemon to dynamically refresh when you make code changes您可以尝试在更改代码时使用 nodemon 动态刷新

https://www.npmjs.com/package/nodemon https://www.npmjs.com/package/nodemon

I agree with @tarek-salem that it's better to use vm library.我同意 @tarek-salem 的观点,即最好使用vm库。 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 common import cache because require and common import has the same cache and the dynamic import has its own cache).无法清除您使用的动态导入缓存(顺便说一下,有一种方法可以清除公共导入缓存,因为require和公共import具有相同的缓存,而动态import有自己的缓存)。 But you can use require instead of dynamic import.但是您可以使用 require而不是动态导入。 To do it first create require in parser.mjs首先在parser.mjs中创建 require

import Module from "module";
const require = Module.createRequire(import.meta.url);  

Then you have 2 options:那么你有两个选择:

  1. Easier: convert look.mjs into commonjs format (rename it look.cjs and use module.exports ).更简单:将look.mjs转换为 commonjs 格式(将其重命名为look.cjs并使用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如果想让importrequire look.mjs 成为可能,你应该使用 package.json创建 npm 包

     { "main": "./look.cjs", "type": "commonjs" }

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' .在这种情况下,在parser.mjs中,您将能够使用require('look')和在其他文件中import('look')import * as look from 'look'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM