Node.js中无需临时文件评估JS ES6模块并调用导出函数的最优方法
Node.js 从内存字符串加载ES模块的可行方案
你遇到的报错本质是默认的vm执行模式仅支持普通脚本,不识别ES模块的import/export语法,下面是两种原生无依赖的实现方案,完全不需要写入临时文件:
方案1:Data URI 导入(最简方案,推荐)
Node.js 14.13+ 原生支持通过data URI直接导入ES模块,代码量最少,适配绝大多数场景:
// js 是你转译后得到的ES模块源代码字符串 const js = `export default () => console.log('目标函数执行成功')`; // 把代码转成base64编码的data URI,指定MIME类型为javascript模块 const moduleDataUri = `data:text/javascript;base64,${Buffer.from(js).toString('base64')}`; // 动态导入即可直接拿到导出内容 const { default: page } = await import(moduleDataUri); // 直接调用目标函数 page();
如果你的模块内包含相对路径导入,只要你调用import时的执行路径和原本写临时文件时的路径一致,就可以正常解析。
方案2:vm 模块ES模式(适合需要上下文隔离的场景)
如果你需要把加载的模块和主程序的上下文隔离开,避免全局变量污染,可以用node:vm提供的SourceTextModule专门处理ES模块:
import vm from 'node:vm'; const js = `export default (name) => \`hello \${name}\``; // 构造ES模块实例,可自定义暴露给模块的全局变量 const module = new vm.SourceTextModule(js, { context: vm.createContext({ console, process, // 你可以在这里加任意需要暴露给模块的全局对象 }) }); // 处理模块内的外部依赖导入 await module.link(async (specifier) => { const importedModule = await import(specifier); return new vm.SyntheticModule( Object.keys(importedModule), function () { Object.keys(importedModule).forEach(key => this.setExport(key, importedModule[key])); } ); }); // 执行模块代码 await module.evaluate(); // 拿到默认导出的目标函数 const page = module.namespace.default; console.log(page('test')); // 输出 hello test
内容的提问来源于stack exchange,提问作者citykid
相关产品推荐
相关产品推荐

