Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load web worker using webpack's worker loader

I'm trying to load a web worker script into my React application by using webpack's worker loader. However, I get a module not found error.

ERROR in ./src/index.js Module not found: Error: Can't resolve './file.worker' in 'C:\Users\wyrm\Documents\Project\src'

This is my src/index.js which is the entry point for webpack

import React from "react";
import ReactDOM from "react-dom";
import Worker from "./file.worker";

const worker = new Worker();
worker.postMessage({ message: "Hello there" });

const Index = () => <div>Hello there General Kenobi!</div>;

ReactDOM.render(<Index />, document.getElementById("index"));

I have my web worker script called file.worker.js in the Project/public folder

/* eslint-env worker */

onmessage = e => {
  const message = e.data;
  console.log(`[From Main]: ${message}`);
};

And this is my webpack config file:

const HtmlWebPackPlugin = require("html-webpack-plugin");

const htmlPlugin = new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html"
});

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [{ loader: "babel-loader" }, { loader: "eslint-loader" }]
      },
      {
        test: /\.worker\.js$/,
        use: [{ loader: "worker-loader", options: { publicPath: "/public/" } }]
      }
    ]
  },
  plugins: [htmlPlugin]
};

According to the webpack documentation, all I need to do is to add the following to my config file, which I have done:

// webpack.config.js
{
  module: {
    rules: [
      {
        test: /\.worker\.js$/,
        use: { loader: 'worker-loader' }
      }
    ]
  }
}

I went to the further step of specifying the public path as documented here:

// App.js
// This will cause the worker to be downloaded from `/workers/file.worker.js`
import Worker from './file.worker.js';

// webpack.config.js
{
  loader: 'worker-loader'
  options: { publicPath: '/workers/' }
}

But even though I have specified the publicPath to be Project/public, the error thrown seems to indicate that it's looking in the Project/src folder for the web worker script. It also seems to me that webpack looks for the web worker script in the Project/public folder by default anyway, so by right it should be redundant to specify Project/public for the publicPath?

I should also mention that I'm using webpack dev server. Could it be that I'm missing some sort of configuration for my webpack dev server, and it's not picking up my web worker script?

I really can't figure out why I'm getting a module not found error when it seems like I've followed the documentation properly.

Project directory
Project
- dist
  - index.html
  - main.js
- public
  - file.worker.js
- src
  - index.html
  - index.js
- .babelrc
- .eslintrc.json
- package.json
- webpack.config.js
like image 565
user3549254 Avatar asked Dec 29 '18 02:12

user3549254


People also ask

Does worker loader work with Webpack 5?

Webpack 5 and Worker Loader Still, in my experience, besides a few quirks, worker-loader can be used with webpack 5, and it offers several more customization options than webpack 5's built-in web worker support.

What is the difference between service worker and web worker?

Unlike web workers, service workers allow you to intercept network requests (via the fetch event) and to listen for Push API events in the background (via the push event). A page can spawn multiple web workers, but a single service worker controls all the active tabs under the scope it was registered with.

How do you use web workers in react?

The first thing to do is to create the web worker using the Worker constructor. Then inside our button's event listener, we send a number to the worker using worker. postMessage({ num }) . After that, we set a function to listen for errors in the worker.


2 Answers

try the follwing:

import Worker from 'worker-loader!./file.worker.js';

You need to specify which loader(i.e. worker-loader) is going to load the worker explicitly.

Also, i dont think you need to configure the publicPath option.

like image 183
Priyesh Diukar Avatar answered Oct 10 '22 15:10

Priyesh Diukar


Try moving the file.worker.js into src. That's where you're looking for it with import Worker from "./file.worker";

like image 28
Tom Duckworth Avatar answered Oct 10 '22 13:10

Tom Duckworth