Webpack loader module for integrating Web Workers into webpack-bundled applications
npx @tessl/cli install tessl/npm-worker-loader@3.0.0Worker Loader is a webpack loader that enables developers to easily integrate Web Workers into their webpack-bundled applications. It provides flexible configuration options for worker instantiation, customizable filename patterns, inline mode for embedding workers as BLOBs, and seamless integration with modern JavaScript features.
npm install worker-loader --save-devWorker Loader generates factory functions that can be imported using standard ES modules or CommonJS syntax:
// ES modules (default, when esModule: true)
import Worker from "./my.worker.js";
// CommonJS (when esModule: false)
const Worker = require("./my.worker.js");
// Inline loader syntax (ES modules)
import Worker from "worker-loader!./Worker.js";
// Inline loader syntax (CommonJS)
const Worker = require("worker-loader!./Worker.js");Worker Loader can be used in two primary ways:
module.exports = {
module: {
rules: [
{
test: /\.worker\.(c|m)?js$/,
use: {
loader: "worker-loader",
options: {
// Configuration options
},
},
},
],
},
};import Worker from "worker-loader!./Worker.js";
// With options as query parameters
import Worker from "worker-loader?filename=custom.worker.js!./Worker.js";// 1. Create a worker file (e.g., my.worker.js)
// my.worker.js
onmessage = function (event) {
const workerResult = event.data;
workerResult.processed = true;
postMessage(workerResult);
};
// 2. Import and use the worker in your main application
import Worker from "./my.worker.js";
const worker = new Worker();
worker.onmessage = function (event) {
console.log("Received from worker:", event.data);
};
worker.postMessage({ data: "Hello worker!" });Creates Web Worker or SharedWorker instances with customizable constructor options.
// Generated worker factory function interface
interface WorkerFactory {
(): Worker | SharedWorker;
}
// Configuration for worker type
interface WorkerTypeConfig {
type: string; // Constructor name (e.g., "Worker", "SharedWorker")
options?: WorkerOptions; // Worker constructor options
}
interface WorkerOptions {
type?: "classic" | "module";
credentials?: "omit" | "same-origin" | "include";
name?: string;
}Configure the loader behavior through webpack configuration options.
interface WorkerLoaderOptions {
worker?: string | WorkerTypeConfig; // Default: "Worker"
publicPath?: string | ((pathData: any, assetInfo: any) => string);
filename?: string | ((pathData: any) => string);
chunkFilename?: string;
inline?: "no-fallback" | "fallback";
esModule?: boolean; // Default: true
}Specifies the worker constructor type and options.
String format:
{
worker: "SharedWorker"
}Object format:
{
worker: {
type: "SharedWorker",
options: {
type: "classic",
credentials: "omit",
name: "my-custom-worker-name"
}
}
}Controls the public URL path for worker files.
String format:
{
publicPath: "/scripts/workers/"
}Function format:
{
publicPath: (pathData, assetInfo) => {
return `/scripts/${pathData.hash}/workers/`;
}
}Customizes the filename pattern for worker entry chunks.
String format:
{
filename: "[name].[contenthash].worker.js"
}Function format:
{
filename: (pathData) => {
if (/\.worker\.(c|m)?js$/i.test(pathData.chunk.entryModule.resource)) {
return "[name].custom.worker.js";
}
return "[name].js";
}
}Sets the filename pattern for worker non-entry chunks.
{
chunkFilename: "[id].[contenthash].worker.js"
}Enables inline worker mode using Blob URLs to avoid cross-origin issues.
{
inline: "fallback" // Creates fallback file for unsupported browsers
}{
inline: "no-fallback" // Inline only, no fallback file
}Controls whether generated code uses ES modules or CommonJS syntax.
{
esModule: false // Use CommonJS: module.exports = function...
}Handle cross-origin restrictions with inline workers.
// Runtime inline worker function (from runtime/inline.js)
// Creates workers using Blob URLs with progressive fallback strategies
function inlineWorker(
content: string, // Worker source code content
workerConstructor: string, // Constructor name ("Worker", "SharedWorker", etc.)
workerOptions?: object, // Worker constructor options
url?: string // Fallback URL for unsupported environments
): Worker | SharedWorker
// Fallback strategy:
// 1. Try Blob API with URL.createObjectURL()
// 2. Try data: URL with encoded content
// 3. Fall back to external URL if provided
// 4. Throw error if no fallback availableUsage with inline option:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.worker\.js$/,
loader: "worker-loader",
options: {
inline: "fallback"
}
}
]
}
};
// Your application code remains the same
import Worker from "./file.worker.js";
const worker = new Worker();For TypeScript projects, define custom module declarations.
// typings/worker-loader.d.ts
declare module "worker-loader!*" {
class WebpackWorker extends Worker {
constructor();
}
export default WebpackWorker;
}TypeScript usage:
import Worker from "worker-loader!./Worker.ts";
const worker = new Worker();
worker.postMessage({ data: "Hello from TypeScript!" });
worker.onmessage = (event) => {
console.log("Worker response:", event.data);
};The loader generates different code patterns based on configuration:
export default function Worker_fn() {
return new Worker(__webpack_public_path__ + "worker.worker.js");
}module.exports = function Worker_fn() {
return new Worker(__webpack_public_path__ + "worker.worker.js");
}export default function SharedWorker_fn() {
return new SharedWorker(
__webpack_public_path__ + "worker.worker.js",
{ "type": "classic", "name": "my-worker" }
);
}import worker from "!!./runtime/inline.js";
export default function Worker_fn() {
return worker(
/* worker source code */,
"Worker",
/* worker options */,
/* fallback url */
);
}For ES6+ features in workers, combine with babel-loader:
module.exports = {
module: {
rules: [
{
test: /\.worker\.(c|m)?js$/i,
use: [
{
loader: "worker-loader"
},
{
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
}
]
}
]
}
};Using function-based filename for dynamic naming:
module.exports = {
module: {
rules: [
{
test: /\.worker\.js$/,
loader: "worker-loader",
options: {
filename: (pathData) => {
const workerName = pathData.chunk.entryModule.resource
.split("/")
.pop()
.replace(".worker.js", "");
return `workers/${workerName}.[contenthash].js`;
}
}
}
]
}
};Worker Loader automatically handles WebAssembly modules in workers:
// worker-with-wasm.worker.js
import wasmModule from "./calculator.wasm";
onmessage = async function(event) {
const wasm = await wasmModule();
const result = wasm.calculate(event.data.numbers);
postMessage({ result });
};Worker Loader handles various error scenarios:
inline: "fallback" is used, unsupported browsers fall back to external filesconst worker = new Worker();
worker.onerror = function(error) {
console.error("Worker error:", error);
};
worker.onmessageerror = function(error) {
console.error("Worker message error:", error);
};