10

I've been using the webpack webworker loader for a while now. And we're now migrating to Angular 7 and started using typescript.

After following many guides and tuturials and this amazing issue post: https://github.com/webpack-contrib/worker-loader/issues/94#issuecomment-336596520

I keep getting errors and do not get the worker-loader to work with typescript.

ERROR in [at-loader] ....../import/worker/index.ts:4:58 TS2306: File '....../import/worker/import.worker.ts' is not a module.

ERROR in [at-loader] ......./import/import.component.ts:13:11 TS2304: Cannot find name 'MyWorkerImport'.

My current setup is as follows:

webpack config:

module: {
    rules: [
        {
            test: /\.worker\.ts$/,
            use: [
                {
                    loader: 'worker-loader',
                    options: {
                        name: '[name].[hash].js',
                        publicPath: '/'
                    }
                },
                {
                    loader: 'awesome-typescript-loader',
                    options: {
                        configFileName: rootPath + '/tsconfig.json'
                    }
                }
            ]
        }
    ]
}

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "lib": [ "es6", "dom" ],
        "noImplicitAny": false,
        "suppressImplicitAnyIndexErrors": true,
        "declaration": false,
        "skipLibCheck": true,
        "types": [
            "node"
        ],
        "typeRoots": [
            "node_modules/@types",
            "typings"
        ]
    },
    "files": []
}

typings/custom.d.ts

declare module 'worker-loader!*' {
    class WebpackWorker extends Worker {
        constructor();
    }

    export = WebpackWorker;
}

worker/import.worker.ts

import { MyWorker, MESSAGE_TYPE } from './types';

const ctx: MyWorker= self as any;

ctx.onmessage = event => {
    const msg = event.data;
    console.log(event);
};

ctx.postMessage({ type: MESSAGE_TYPE.READY });

export default null as any;

worker/index.ts

import { MyWorker} from './types';
import MyWorkerImport = require('./import.worker');

export { MESSAGE_TYPE } from './types';
export default MyWorkerImport as typeof MyWorker;

worker/types.d.ts

// MyWorker/types.d.ts

// Enumerate message types
export const enum MESSAGE_TYPE {
    READY = 'ready',
    REQUEST = 'request',
    RESULT = 'result',
    ERROR = 'error'
}

// Define expected properties for each message type
interface IReadyMessage {
    type: MESSAGE_TYPE.READY;
}

interface IRequestMessage {
    type: MESSAGE_TYPE.REQUEST;
    paramA: string;
    paramB: number;
}

interface IResultMessage {
    type: MESSAGE_TYPE.RESULT;
    data: Float32Array;
}

interface IErrorMessage {
    type: MESSAGE_TYPE.ERROR;
    error: string;
}

// Create a union type of all messages for convenience
type MyWorkerMessage = IReadyMessage | IRequestMessage | IResultMessage | IErrorMessage;

// Extend MessageEvent to use our messages
interface IMyMessageEvent extends MessageEvent {
    data: MyWorkerMessage;
}

// Extend Worker to use our custom MessageEvent
export class MyWorkerWorker extends Worker {
    public onmessage: (this: MyWorker, ev: IMyMessageEvent) => any;

    public postMessage(this:  MyWorker, msg: MyWorkerMessage, transferList?: ArrayBuffer[]): any;
    public addEventListener(type: 'message', listener: (this: MyWorker, ev: IMyMessageEvent) => any, useCapture?: boolean): void;
    public addEventListener(type: 'error', listener: (this: MyWorker, ev: ErrorEvent) => any, useCapture?: boolean): void;
}

import.component.ts

import {Component, OnInit} from '@angular/core';
import MyWorker from "./worker"

@Component({
    templateUrl: './import.a2.html',
    styleUrls: ['./import.a2.scss']
})
export class ImportComponent implements OnInit {

    workers: MyWorker[] = [];

    constructor() {}

    ngOnInit(): void {}

    processFile() {
        const worker = new MyWorker('');
    }

}

And i keep getting the following message:

ERROR in [at-loader] ....../import/worker/index.ts:4:58 TS2306: File '....../import/worker/import.worker.ts' is not a module.

ERROR in [at-loader] ......./import/import.component.ts:13:11 TS2304: Cannot find name 'MyWorkerImport'.

if i change the line to

import MyWorker = require('worker-loader!./import.worker');

The error changes to:

ERROR in [at-loader] ....../import/worker/index.ts:4:58 TS2307: Cannot find module 'worker-loader!./import.worker'.

ERROR in [at-loader] ....../import/import.component.ts:13:11 TS2304: Cannot find name 'MyWorkerImport'.

2 Answers 2

8

Ok all an all it's plain and simple. My custom typings file was not included and webpack did not get that.

I changed the custom.d.ts to a folder named custom and a file named index.d.ts resulting in typings/custom/index.d.ts

I changed tsconfig.json to include typings relative and to add custom (since it was fixed at node).

more info on typings here: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html (Search for @typeRoots)

New tsconfig (note the difference in types and typeRoots):

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": true,
        "emitDecoratorMetadata": true,
        "experimentalDecorators": true,
        "lib": [ "webworker", "es6", "dom" ],
        "noImplicitAny": false,
        "suppressImplicitAnyIndexErrors": true,
        "declaration": false,
        "skipLibCheck": true,
        "types": [
            "node",
            "custom"
        ],
        "typeRoots": [
            "node_modules/@types",
            "./typings"
        ]
    },
    "files": []
}

Next to that you must load the file as

import MyWorker = require('worker-loader!./worker/import.worker');

and you can remove the entire webpack config section

Sign up to request clarification or add additional context in comments.

Comments

0

I made the suggested changes and it didn't work for me. For those not using Vue I suggest trying to update Webpack. for those who use Vue I had the same problems and I managed to fix it by updating vue-cli to 5.0.6 and using vue upgrade command. This command will also update the Webpack

Migrate Vue CLI from v4 link

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.