使用cachedData创建vm.SourceTextModule时触发TypeError问题咨询
问题分析与解决方案
不是设置cachedData后就无法使用import()语法,问题出在缓存数据的创建时机和回调绑定的逻辑上。
核心原因
调用mod1.createCachedData()时,缓存数据仅包含模块编译阶段的信息,此时模块尚未触发动态导入逻辑,且importModuleDynamically回调不会被序列化到缓存中。当用该缓存创建mod2时,Node.js处理动态导入时无法从缓存中找到回调关联,即便创建mod2时传入了回调,也会因缓存优先级导致回调未被正确绑定。
解决方案
调整缓存创建时机,确保动态导入的回调逻辑在缓存生成前已被正确关联。具体来说,需先完成模块的link操作,再生成缓存数据:
import vm from "vm"; let context = vm.createContext({console}) async function importModuleDynamically(name) { let stt = new vm.SyntheticModule(['name'], function () { this.setExport('name', name) }) await stt.link(() => null) await stt.evaluate() return stt } function initializeImportMeta(meta, module) { meta.url = module.identifier } let code = 'export default () => import("fs")' // 先创建模块并完成link,确保动态导入回调被关联后再生成缓存 let mod1 = new vm.SourceTextModule(code, { context, identifier: 'mod1', importModuleDynamically, initializeImportMeta }) // 先执行link,让Node.js识别动态导入的回调依赖 await mod1.link(() => null) // 此时生成的缓存会包含动态导入的绑定信息 let cachedData = mod1.createCachedData() await mod1.evaluate() console.log(await mod1.namespace.default()) let mod2 = new vm.SourceTextModule(code, { context, identifier: 'mod1', cachedData, importModuleDynamically, initializeImportMeta }) await mod2.link(() => null) await mod2.evaluate() console.log(await mod2.namespace.default()) console.log(mod1, mod2)
关键说明
createCachedData()必须在模块link之后调用,这样缓存才会包含模块对动态导入回调的依赖标记,后续用缓存创建模块时,传入的importModuleDynamically才能被正确识别。- Node.js的vm模块缓存不会存储回调函数本身,仅存储模块结构和依赖关系,因此必须提前通过
link让模块标记动态导入需求,确保后续回调生效。
内容的提问来源于stack exchange,提问作者Time Killer
相关产品推荐
相关产品推荐

