Search code examples
typescriptwebpackweb-workerwebpack-5

Web Workers written in Typescript in Webpack 5: SyntaxError: Cannot use import statement outside a module


Webpack 5 documentation mentions that worker-loader is not needed anymore, and it seems easy for javascript files. However, I am using Typescript, and I'm not able to get my worker.js output file working properly. When I launch load the webworker with const worker = new Worker(workerPath);, I get

Uncaught SyntaxError: Cannot use import statement outside a module

Note: my workerPath is "dist/app.worker.js" and this file exists, but it sadly contains either import or require statements, which don't work in the browser. I think need to bundle these together, but I'm not sure how. Currently, it contains the following code, and I hoped that auth.ts will be bundled in:

import Auth from "./auth";

Solution

  • Instead of using worker-loader or the default webpack config using module.export = {...}, I exported multiple configurations. Specifically, I created 2 entry points (main and worker in webpack.config.js, and used module.exports = [main, worker]. In the code, I referenced the second entry point using const workerPath = "./dist/worker_name.worker.js".

    My webpack.config.js

    const path = require('path')
    
    const main = {
        entry: "./src/index.ts",
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
            publicPath: "dist/"
        },
        context: __dirname,
        devtool: "source-map",
        mode: "development",
        resolve: {
            modules: [
                'src',
                'node_modules'
            ],
            extensions: [
                '.js',
                '.ts',
                '.tsx'
            ],
            plugins: [],
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true,
                    },
                },
            ],
        },
    }
    
    const worker = {
        entry: "./src/worker_name.worker.ts",
        output: {
            filename: 'worker_name.worker.js',
            path: path.resolve(__dirname, 'dist'),
            publicPath: "dist/"
        },
        target: "webworker",
        devtool: "source-map",
        mode: "development",
        resolve: {
            modules: [
                'src',
                'node_modules'
            ],
            extensions: [
                '.js',
                '.ts',
                '.tsx'
            ],
            plugins: [],
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true,
                    },
                },
            ],
        },
    }
    
    
    module.exports = [main, worker]
    

    You can probably refactor the above to make it shorter by sharing code between them.