Webpack worker-loader fails to compile typescript worker

Thanks Dmitry, you helped me get much further along in getting worker-loader to build my Typescript project.

Even so I had three more issues I needed to solve in order to get it to work:

  • The build would hang when I added worker-loader above ts-loader/awesome-typescript-loader. I fixed this by making the import paths be much more specific for types that were imported/exported from the web worker module. I found out by trying to comment out the content of the web worker entry file, and then uncomment one line at a time, to see what would and wouldn't build.

  • The second thing I did wrong was that I added worker-loader both as a rule my webpack config, and in the import statement. I was basically running worker-loader twice on the web worker module. Doh. So either add worker-loader to your webpack config or add 'worker-loader!' to the import/require statement. I added worker-loader to my webpack config and the just imported like this: import MyWorker = require('./my-worker');

  • I got a typeerror MyWorker is not a constructor when I tried to do new MyWorker(), and had to cast MyWorker to any for the Typescript type checker to swallow it: new (MyWorker as any)();

Hope this helps somebody.


Ok I figured it out.

First I needed to move worker loader before the ts-loader and did not need to specify array in worker use property and just keep it as described in documentation of 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'] },
    ]
  },

Then in my worker I also needed to export anything otherwise typescript (2.8.3) would complain that it can't find a module and I export default null as any to avoid confusing ts even further.

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({});