Webpack 的 worker-loader 无法编译 TypeScript worker

13
我正在按照 worker-loader 文档中的描述配置我的项目,并且使用正确的 d.ts 工作,使得 TS 代码智能提示正常运行。

然而,在 webpack 构建期间,它会抛出一个错误,我不知道为什么。

 ERROR in ./src/test.worker.ts
Module parse failed: Unexpected token (1:9)
You may need an appropriate loader to handle this file type.
| const ctx: Worker = self as any;
| ctx.addEventListener('message', event => {
|   console.log(event);

我的工作文件内容 test.worker.ts:

const ctx: Worker = self as any;
ctx.addEventListener('message', event => {
  console.log(event);
  setTimeout(() => ctx.postMessage({
    foo: 'boo'
  }), 5000);
});

应用程序入口 index.ts

import TestWorker from './test.worker.ts';

const test = new TestWorker();
test.postMessage({});

最后,这是我的webpack.config.js文件

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const DIR_SOURCE = path.resolve(__dirname, 'src');
const DIR_BUILD = path.resolve(__dirname, 'build');

module.exports = {

  entry: `${DIR_SOURCE}/index.tsx`,

  output: {
    path: DIR_BUILD,
    filename: 'project.bundle.js'
  },

  devtool: "source-map",

  resolve: {
    // Add '.ts' and '.tsx' as resolvable extensions.
    extensions: [".ts", ".tsx", ".js", ".json"]
  },

  module: {
    rules: [
      {test: /\.tsx?$/, loader: "ts-loader" },
      {test: /\.worker\.ts$/, use: ['ts-loader', 'worker-loader'] },
      {test: [/\.vert$/, /\.frag$/], use: 'raw-loader'},
      {test: /\.(png|jpg|gif|svg)$/, use: {loader: 'file-loader', options: {}} },
      {test: /.*\.sass/, use: ['style-loader', 'css-loader', 'sass-loader'] },
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      'CANVAS_RENDERER': JSON.stringify(true),
      'WEBGL_RENDERER': JSON.stringify(true)
    }),
    new HtmlWebpackPlugin({
      template: 'src/index.ejs'
    }),
  ]
};

非常感谢任何帮助。

谢谢:)

2个回答

25

好的,我想通了。

首先我需要在ts-loader之前移动worker loader,并且不需要在worker use属性中指定数组,只需要按照worker-loader的文档描述保持它即可。

module: {
    rules: [
      {test: /\.worker\.ts$/, loader: 'worker-loader'},
      {test: /\.tsx?$/, loader: "ts-loader" },
      {test: [/\.vert$/, /\.frag$/], use: 'raw-loader'},
      {test: /\.(png|jpg|gif|svg)$/, use: {loader: 'file-loader', options: {}} },
      {test: /.*\.sass/, use: ['style-loader', 'css-loader', 'sass-loader'] },
    ]
  },

然后在我的worker中,我还需要导出任何东西,否则Typescript (2.8.3)会抱怨找不到一个模块,所以我使用export default null as any避免让ts更加困惑。

worker.js

const ctx: Worker = self as any;
ctx.addEventListener('message', event => {
  console.log(event);
  setTimeout(() => ctx.postMessage({
    foo: 'boo'
  }), 5000);
});
export default null as any;

index.js

import TestWorker from './test.worker.ts';
const test = new TestWorker('');
test.postMessage({});

2
这对我不起作用。最终编译成了 var test_worker_1 = __webpack_require__('./src/test.worker.ts'); var worker = new test_worker_1.default();。它应该编译为 ... new test_worker_1(); - Nicholas Albion
ts需要一个编译模块。为了避免这个空问题,我们只需要添加一个虚拟类声明来替换这个"export default null as any"。 constructor() { super(""); } } - Shen liang
1
export default null 这一行代码让我既高兴又难过,因为它挽救了我的理智。谢谢! - elpoto

5

谢谢 Dmitry,你帮我解决了使用 worker-loader 编译 TypeScript 项目的问题。

然而,我还需要解决三个问题才能使它正常工作:

  • 当我在 ts-loader/awesome-typescript-loader 上方添加 worker-loader 时,构建过程会挂起。我通过让导入路径更具体地指定从 Web Worker 模块中导入/导出的类型来解决了这个问题。我尝试逐行注释 Web Worker 入口文件的内容,再逐行取消注释,以查看哪些会和哪些不会编译,最终找到了解决办法。

  • 第二个问题是我在 webpack 配置规则和 import 语句中都添加了 worker-loader。我实际上在 Web Worker 模块上运行了两次 worker-loader。因此,只需将 worker-loader 添加到 webpack 配置中或在 import/require 语句中添加 'worker-loader!'。我将 worker-loader 添加到了我的 webpack 配置中,然后像这样导入: import MyWorker = require('./my-worker');

  • 当我尝试使用 new MyWorker() 时,出现了一个“typeerror MyWorker is not a constructor”的错误,并且必须将 MyWorker 强制转换为 any 才能被 TypeScript 类型检查器接受:new (MyWorker as any)();

希望这能帮到某些人。


我通过将工作线程导出为任何类型来解决了上一个问题:export default null as any; - Dmitry Matveev
3
运行时出现了some_worker.default is not a constructor错误,而不是在构建期间。你是否遇到过类似的情况? - Vicky Leong
@VickyLeong 我之前也遇到了同样的问题,原来是Webpack给我提供了lambda函数而不是构造函数,所以我需要调用它而不是创建新实例。 - icl7126

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接