Reputation: 8961
In an Express.js app, I'm using Babel to precompile to commonjs before starting it. The compilation step looks like this:
babel ./src --out-dir dist
node ./dist/bin
As part of the project I have a file called my-worker.js
where I use import syntax
:
# my-worker.js
import { parentPort, workerData } from 'worker_threads'
import axios from 'axios'
...
And that is used by other-file.js
:
#other-file.js
...
const worker = new Worker(__dirname + '/my-worker.js', { workerData: ... })
...
This works fine. Babel converts all the files to commonjs, and loading the worker script works.
BUT
When I use @babel/node
, this doesn't work:
babel-node ./src/bin
I get the warning:
(node:4865) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
Along with the error:
Cannot use import statement outside a module
I don't want to use "type": "module"
, since then I have to explicitly name file extensions, and also I'm not sure that import X, { y } from ...
syntax is supported (which I like).
If I change my worker file to be my-worker.mjs
, and change the new Worker
statement accordingly, then that works with @babel/node
, but not with my production build since filenames are changed back to .js
.
How can I get @babel/node
to load and cache (I guess this is what it needs to do?) files loaded by a Worker? Why does this work with @babel
and not with @babel/node
?
My .babelrc
file looks like this:
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"targets": {
"node": "13"
},
"modules": "commonjs"
}
]
]
}
Upvotes: 4
Views: 978
Reputation: 2509
The @babel/register
API can help dynamically transpile a script source, as pointed out in https://github.com/babel/babel/issues/10972#issuecomment-572608142
You can use this approach with eval mode to make a single-file script. This might be useful if you use babel-node
to run a command-line utility script.
import { isMainThread, Worker, workerData } from "worker_threads";
function createTranspiledWorker(filename, options) {
const transpile = `
require('@babel/register');
require(${JSON.stringify(filename)});
`;
return new Worker(transpile, { ...options, eval: true });
}
async function main() {
const w = createTranspiledWorker(__filename, { workerData: { hello: "world" } });
const exit = new Promise(resolve => w.on("exit", resolve));
await exit;
}
function worker() {
console.log("worker", workerData);
}
if (isMainThread) {
main();
} else {
worker();
}
Upvotes: 4