当 importModuleDynamically 是一个函数时


【When importModuleDynamically is a function】

importModuleDynamically 是一个函数时,它将在编译后的代码中调用 import() 时被调用,以便用户自定义请求的模块应该如何被编译和执行。目前,Node.js 实例必须使用 --experimental-vm-modules 标志启动才能使用此选项。如果未设置该标志,则此回调将被忽略。如果被执行的代码实际上调用了 import(),结果将会以 ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG 拒绝。

【When importModuleDynamically is a function, it will be invoked when import() is called in the compiled code for users to customize how the requested module should be compiled and evaluated. Currently, the Node.js instance must be launched with the --experimental-vm-modules flag for this option to work. If the flag isn't set, this callback will be ignored. If the code evaluated actually calls to import(), the result will reject with ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG.】

回调 importModuleDynamically(specifier, referrer, importAttributes) 的签名如下:

【The callback importModuleDynamically(specifier, referrer, importAttributes) has the following signature:】

  • specifier <string> 传递给 import() 的指定符
  • referrer <vm.Script> | <Function> | <vm.SourceTextModule> | <Object> referrer 是针对 new vm.Scriptvm.runInThisContextvm.runInContextvm.runInNewContext 编译后的 vm.Script。对于 vm.compileFunction 是编译后的 Function,对于 new vm.SourceTextModule 是编译后的 vm.SourceTextModule,对于 vm.createContext() 则是上下文 Object
  • importAttributes <Object> 传递给 optionsExpression 可选参数的 "with" 值,如果未提供值,则为一个空对象。
  • phase <string> 动态导入的阶段("source""evaluation")。
  • 返回值:<Module Namespace Object> | <vm.Module> 推荐返回 vm.Module,以便利用错误跟踪,并避免包含 then 函数导出的命名空间出现问题。
// This script must be run with --experimental-vm-modules.
import { Script, SyntheticModule } from 'node:vm';

const script = new Script('import("foo.json", { with: { type: "json" } })', {
  async importModuleDynamically(specifier, referrer, importAttributes) {
    console.log(specifier);  // 'foo.json'
    console.log(referrer);   // The compiled script
    console.log(importAttributes);  // { type: 'json' }
    const m = new SyntheticModule(['bar'], () => { });
    await m.link(() => { });
    m.setExport('bar', { hello: 'world' });
    return m;
  },
});
const result = await script.runInThisContext();
console.log(result);  //  { bar: { hello: 'world' } }// This script must be run with --experimental-vm-modules.
const { Script, SyntheticModule } = require('node:vm');

(async function main() {
  const script = new Script('import("foo.json", { with: { type: "json" } })', {
    async importModuleDynamically(specifier, referrer, importAttributes) {
      console.log(specifier);  // 'foo.json'
      console.log(referrer);   // The compiled script
      console.log(importAttributes);  // { type: 'json' }
      const m = new SyntheticModule(['bar'], () => { });
      await m.link(() => { });
      m.setExport('bar', { hello: 'world' });
      return m;
    },
  });
  const result = await script.runInThisContext();
  console.log(result);  //  { bar: { hello: 'world' } }
})();