使用worker_thread的Ts节点导致“无法在模块外部使用导入语句”

sli*_*ier 7 typescript ts-node

我有这个简单的代码来尝试工作线程。

// thread.ts
import { Worker, isMainThread } from 'worker_threads';

if (isMainThread) {
    const worker = new Worker(__filename);
} else {
    console.log('hello from worker');
}
Run Code Online (Sandbox Code Playgroud)

显然,当我尝试使用 运行该文件时ts-node thread.ts,出现此错误:

(node:13200) 警告:要加载 ES 模块,请在 package.json 中设置 "type": "module" 或使用 .mjs 扩展名。

语法错误:无法在模块外部使用 import 语句

但是如果我手动编译并调用该文件tsc && dist/thread.js,它就可以正常工作

我尝试进一步实验,如果我将要在工作线程内运行的代码放在外部文件中,那么它也可以正常工作

// thread.ts
import { Worker, isMainThread } from 'worker_threads';
const worker = new Worker('./src/worker.ts');
Run Code Online (Sandbox Code Playgroud)

这是我的 tsconfig.json

{
    "compilerOptions": {
        "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
        "module": "commonjs", /* Specify what module code is generated. */
         "rootDir": "./src", /* Specify the root folder within your source files. */
         "outDir": "./dist", /* Specify an output folder for all emitted files. */
         "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */
        "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
        "strict": true, /* Enable all strict type-checking options. */
        "skipLibCheck": true /* Skip type checking all .d.ts files. */
    }
}
Run Code Online (Sandbox Code Playgroud)

有人可以启发我吗?

Mat*_*age 11

对我来说真正有帮助的是添加:

execArgv: ["--require", "ts-node/register"]
Run Code Online (Sandbox Code Playgroud)

...工人的选择。但因为在我的例子中,我将 TS 转换为 JS 进行生产,并且我不想将 ts-node 作为生产依赖项,所以我编写了这个函数:

import { Worker, WorkerOptions } from "worker_threads";

function importWorker(path: string, options: WorkerOptions) {
  const resolvedPath = require.resolve(path);
  return new Worker(resolvedPath, {
    ...options,
    execArgv: /\.ts$/.test(resolvedPath) ? ["--require", "ts-node/register"] : undefined,
  });
}
Run Code Online (Sandbox Code Playgroud)

当我调用这个函数时,我不会添加扩展,就像我们在常规导入中所做的那样。


小智 1

作为工作人员启动 .ts 文件时遇到类似的问题,这是我设法做到这一点的方法首先,我使用包装函数创建一个工作人员实例:

import { Worker } from 'worker_threads';
const workerTs = (file: string, wkOpts: WorkerOptions & any) => {


wkOpts.eval = true;
  if (!wkOpts.workerData) {
    wkOpts.workerData = {};
  }

  wkOpts.workerData.__filename = file;
  return new Worker(`
          const wk = require('worker_threads');
          require('tsconfig-paths/register');
          require('ts-node').register({
            "compilerOptions": {
              "target": "es2016",
              "esModuleInterop": true,
              "module": "commonjs",
              "rootDir": ".",
            }
          });
          let file = wk.workerData.__filename;
          delete wk.workerData.__filename;
          require(file);
      `,
    wkOpts
  );
};

const worker = workerTs('./worker.ts', { worderData: { /* */ } });
Run Code Online (Sandbox Code Playgroud)

我的worker.ts 看起来像这样:

import { workerData, parentPort } from "worker_threads";

doSmth(workerData);

parentPort.postMessage('done');
Run Code Online (Sandbox Code Playgroud)

希望对您有帮助!