[英]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:那么你有两个选择:
Easier: convert look.mjs
into commonjs format (rename it look.cjs
and use module.exports
).更简单:将
look.mjs
转换为 commonjs 格式(将其重命名为look.cjs
并使用module.exports
)。
If want to make it possible to either import
AND require
look.mjs you should create the npm package with package.json如果想让
import
和require
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.