在 nextjs 上使用打字稿时网络工作者无法正确加载

web worker not loading properly when using typescript on nextjs

我正在为我的项目使用 next js,它使用 Webpack 5 进行捆绑。 根据这个 webworkers 我可以使用以下语法来加载我的网络工作者:

new Worker(new URL('./worker.js', import.meta.url));

但是当我使用以下内容时:

new Worker(new URL('./worker.ts', import.meta.url));

它作为媒体类型文件加载到浏览器上,而不是解析 typescript 的导入和导出。关于如何在下一个 js 上解决这个问题有什么建议吗?

我的 tsconfig:

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  },
  "exclude": ["node_modules", ".next", "out"],
  "include": [
    "next-env.d.ts",
    "global.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.mdx",
    "**/*.js",
    "workers/**/*.ts"
  ]
}

不确定这是否能准确回答您的问题,但这是我用于 Typescript only web worker 体验的一个选项。我认为它非常简洁并且支持一个很好的基于对象的编码模型,所以也许它满足您的要求?

依赖关系

运行 这些命令:

npm install comlink --save
npm install worker-loader --save-dev

定义网络工作者

将此添加到 typings.d.ts 文件:

declare module 'worker-loader!*' {

    class WebpackWorker extends Worker {
        constructor();
    }

    export default WebpackWorker;
}

创建网络工作者

import {expose} from 'comlink';

export class MyWebWorker {

  private readonly name: string;

  public constructor(name: string) {
    this.name = name;
  }  

  public async getData(input: string) : Promise<any> {
    return {
      message: `Hello from web worker, ${name}, ${input}`;
    };
 }
}

expose(MyWebWorker);

使用网络工作者

import {wrap, Remote} from 'comlink';
import Worker from 'worker-loader!./mywebworker';
import {MyWebWorker} from './mywebworker';

export class MyConsumingClass {

  public async callWebWorker(): Promise<void> {
  {
    const RemoteChannel = wrap<typeof MyWebWorker>(new Worker());
    const webWorker: Remote<MyWebWorker> = await new RemoteChannel("some name");
    const data = await webWorker.getData("some input");
    console.log(data.message);
  }
}

WEBPACK 行为

上面的typings.d.ts文件和worker-loader插件意味着webpack 5会输出一个名为mywebworker.bundle.worker.js的文件,注意这是小写的。在实际的 webpack 文件中不需要对 worker-loader 的引用,尽管在我的设置中我使用了这种输出格式,这可能会影响 web worker bundle 的名称:

output: {
    path: path.resolve(__dirname, '../dist'),
    filename: '[name].bundle.js'
}