📝
vm.Script 環境であっても Worker の中では import() が使える
通常、vm.Script
で作った環境の中では import()
が使えません。TypeError [ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING]: A dynamic import callback was not specified.
になります。オプション指定すれば動くんですけど、自分が vm.Script
しているわけではなく、対象のランタイムが勝手にやってる場合もあり、今回はそういうケースを想定しています。
スクリプトなので当然 import mod from "mod";
も使えません。これでは ESM を読み込めなくて困ってしまいます。
しかし、vm.Script
環境であっても worker_threads
の Worker
の中では import()
が使えます。ためしにやってみましょう。
require
を入れたコンテキストを作って vm.Script
環境で script.js
を実行します。
index.js
const vm = require("node:vm");
const fs = require("node:fs");
const path = require("node:path");
const code = fs.readFileSync(path.join(process.cwd(), "script.js"));
const script = new vm.Script(code);
const context = vm.createContext({ require });
script.runInContext(context);
その中で worker_thrcads
の Worker
を作って、worker.js
を実行します。
script.js
const { Worker } = require("node:worker_threads");
const worker = new Worker("./worker.js");
worker.postMessage("msg");
worker.once("message", ({ value }) => {
console.log(value);
});
worker.js
の中で module.mjs
を import()
します。
worker.js
const { parentPort } = require("worker_threads");
parentPort.on("message", () => {
import("./module.mjs").then(({ addOne }) => {
parentPort.postMessage({ value: addOne(1) });
});
});
module.mjs
には適当な関数が生えています。
module.mjs
export function addOne(value) {
return value + 1;
}
なんと動くんですね。vm.Script
環境で動かさないといけない制約がある中で ESM を使いたいときのワークアラウンドですね。やりたくねえ。
Discussion