在带有 typescript 的 webpack5 项目上使用 comlink 与 web-workers 一起工作

ari*_*iel 5 javascript web-worker typescript webpack comlink

我有一个用 Typescript 编写并使用 webpack5 捆绑的项目。我尝试使用网络工作者从最小线程中卸载一些代码。

主要.worker.ts:

import { expose } from 'comlink';
import  {TimeConsumingFunction} from "./TimeConsumingFunction"

const exports = {
    TimeConsumingFunction
};

export type WorkerInterfaceTimeConsumingFunction = typeof exports;
export default null as any;
expose(exports);
Run Code Online (Sandbox Code Playgroud)

主要.ts:

import { wrap } from 'comlink';
import {WorkerInterfaceTimeConsumingFunction, default as DataPixelsWorker} from './main.worker';


const worker = new Worker(new URL("./main.worker", import.meta.url));
const workerApi = wrap(worker);

let result = await workerApi.TimeConsumingFunction();
Run Code Online (Sandbox Code Playgroud)

ts配置:

{
  "compilerOptions": {
    "target": "es3",
    "module": "esnext",
    "lib": ["webworker", "es2018", "dom"],
    "allowJs": true,
    "checkJs": false,
    "sourceMap": true,
    "removeComments": false,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "esModuleInterop": true
},
  "include": [
      "./**/*"
  ],
  "exclude": [
      "./plugins/**/*",
      "./typings/**/*",
      "./dev/**/*",
      "./dist/**/*"
  ]
}
Run Code Online (Sandbox Code Playgroud)

webpack.js:

const path = require('path');

module.exports = [
    {
        entry: './main.ts',
        mode: 'production',
        target: ['web', 'es5'],
        module: 
        {
            rules: 
            [
                {
                    test: /\.worker\.(js|ts)$/,
                    use: { loader: 'worker-loader' }
                },
                {
                    test: /\.tsx?$/,
                    use: 'ts-loader',
                    exclude: /node_modules/
                }
            ]
        },
        resolve: 
        {
            extensions: [ '.tsx', '.ts', '.js' ]
        },
        output: 
        {
            path: path.resolve(__dirname, 'dist'),
            filename: 'main.js'
        },
        optimization: 
        {
            minimize: true,
        },
        stats: 
        {
            colors: true
        }
    }
];
Run Code Online (Sandbox Code Playgroud)

包.json:

{
  "name": "Project",
  "sideEffects": false,
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --progress --config=./webpack.js --mode production --output-path ./dist/."
  },
  "devDependencies": {
    "@babel/core": "^7.14.6",
    "@babel/plugin-proposal-class-properties": "^7.14.5",
    "@babel/plugin-proposal-decorators": "^7.14.5",
    "@babel/plugin-transform-runtime": "^7.14.5",
    "@babel/preset-env": "^7.14.5",
    "@babel/preset-typescript": "^7.14.5",
    "babel-loader": "^8.2.2",
    "ts-loader": "^4.5.0",
    "typescript": "^4.2.4",
    "webpack": "^5.36.0",
    "webpack-cli": "^4.6.0",
    "webpack-version-file-plugin": "^0.4.0",
    "worker-loader": "^3.0.8"
  },
  "dependencies": {
    "@babel/runtime": "^7.14.6",
    "comlink": "^4.3.1",
    "core-js": "^3.11.2"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Run Code Online (Sandbox Code Playgroud)

使用命令转译项目时,npm run build输出包含 2 个文件:

  1. main.js
  2. main.worker.js

输出文件上传到 CDN。文件将从 URL 加载https://www.example.com/main.js

内容从 URL 加载https://www.example-content.com 内容包含以下脚本标签<script src='https://www.example.com/main.js'></script>

加载内容时,浏览器控制台上会出现以下错误:

main.js?x=1111:1 Uncaught (in promise) DOMException: Failed to construct 'Worker': Script at 'https://www.example.com/main.worker.js' 
cannot be accessed from origin 'https://www.example-content.com'.

    at e.<anonymous> (https://www.example.com/main.js?x=1111:1:313839)
Run Code Online (Sandbox Code Playgroud)

因为脚本是从 CDN 加载的,而 CDN 可以通过与加载脚本的内容不同的域进行访问,所以我认为最好的方法是将文件main.worker.js捆绑到main.js中。webpack 5 有办法做到这一点吗?还有其他方法可以解决这个问题吗?