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
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.
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.
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.
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.
Try moving the file.worker.js into src. That's where you're looking for it with import Worker from "./file.worker";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With