1 | <div align="center">
|
2 | <a href="https://github.com/webpack/webpack">
|
3 | <img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
4 | </a>
|
5 | </div>
|
6 |
|
7 | [![npm][npm]][npm-url]
|
8 | [![node][node]][node-url]
|
9 | [![deps][deps]][deps-url]
|
10 | [![tests][tests]][tests-url]
|
11 | [![coverage][cover]][cover-url]
|
12 | [![chat][chat]][chat-url]
|
13 | [![size][size]][size-url]
|
14 |
|
15 | # worker-loader
|
16 |
|
17 | worker loader module for webpack
|
18 |
|
19 | ## Getting Started
|
20 |
|
21 | To begin, you'll need to install `worker-loader`:
|
22 |
|
23 | ```console
|
24 | $ npm install worker-loader --save-dev
|
25 | ```
|
26 |
|
27 | ### Inlined
|
28 |
|
29 | **App.js**
|
30 |
|
31 | ```js
|
32 | import Worker from "worker-loader!./Worker.js";
|
33 | ```
|
34 |
|
35 | ### Config
|
36 |
|
37 | **webpack.config.js**
|
38 |
|
39 | ```js
|
40 | module.exports = {
|
41 | module: {
|
42 | rules: [
|
43 | {
|
44 | test: /\.worker\.js$/,
|
45 | use: { loader: "worker-loader" },
|
46 | },
|
47 | ],
|
48 | },
|
49 | };
|
50 | ```
|
51 |
|
52 | **App.js**
|
53 |
|
54 | ```js
|
55 | import Worker from "./file.worker.js";
|
56 |
|
57 | const worker = new Worker();
|
58 |
|
59 | worker.postMessage({ a: 1 });
|
60 | worker.onmessage = function (event) {};
|
61 |
|
62 | worker.addEventListener("message", function (event) {});
|
63 | ```
|
64 |
|
65 | And run `webpack` via your preferred method.
|
66 |
|
67 | ## Options
|
68 |
|
69 | | Name | Type | Default | Description |
|
70 | | :-----------------------------------: | :-------------------------: | :-----------------------------: | :-------------------------------------------------------------------------------- |
|
71 | | **[`worker`](#worker)** | `{String\|Object}` | `Worker` | Allows to set web worker constructor name and options |
|
72 | | **[`publicPath`](#publicpath)** | `{String\|Function}` | based on `output.publicPath` | specifies the public URL address of the output files when referenced in a browser |
|
73 | | **[`filename`](#filename)** | `{String\|Function}` | based on `output.filename` | The filename of entry chunks for web workers |
|
74 | | **[`chunkFilename`](#chunkfilename)** | `{String}` | based on `output.chunkFilename` | The filename of non-entry chunks for web workers |
|
75 | | **[`inline`](#inline)** | `'no-fallback'\|'fallback'` | `undefined` | Allow to inline the worker as a `BLOB` |
|
76 | | **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax |
|
77 |
|
78 | ### `worker`
|
79 |
|
80 | Type: `String|Object`
|
81 | Default: `Worker`
|
82 |
|
83 | Set the worker type.
|
84 |
|
85 | #### `String`
|
86 |
|
87 | Allows to set web worker constructor name.
|
88 |
|
89 | **webpack.config.js**
|
90 |
|
91 | ```js
|
92 | module.exports = {
|
93 | module: {
|
94 | rules: [
|
95 | {
|
96 | test: /\.worker\.(c|m)?js$/i,
|
97 | loader: "worker-loader",
|
98 | options: {
|
99 | worker: "SharedWorker",
|
100 | },
|
101 | },
|
102 | ],
|
103 | },
|
104 | };
|
105 | ```
|
106 |
|
107 | #### `Object`
|
108 |
|
109 | Allow to set web worker constructor name and options.
|
110 |
|
111 | **webpack.config.js**
|
112 |
|
113 | ```js
|
114 | module.exports = {
|
115 | module: {
|
116 | rules: [
|
117 | {
|
118 | test: /\.worker\.(c|m)?js$/i,
|
119 | loader: "worker-loader",
|
120 | options: {
|
121 | worker: {
|
122 | type: "SharedWorker",
|
123 | options: {
|
124 | type: "classic",
|
125 | credentials: "omit",
|
126 | name: "my-custom-worker-name",
|
127 | },
|
128 | },
|
129 | },
|
130 | },
|
131 | ],
|
132 | },
|
133 | };
|
134 | ```
|
135 |
|
136 | ### `publicPath`
|
137 |
|
138 | Type: `String|Function`
|
139 | Default: based on `output.publicPath`
|
140 |
|
141 | The `publicPath` specifies the public URL address of the output files when referenced in a browser.
|
142 | If not specified, the same public path used for other webpack assets is used.
|
143 |
|
144 | #### `String`
|
145 |
|
146 | **webpack.config.js**
|
147 |
|
148 | ```js
|
149 | module.exports = {
|
150 | module: {
|
151 | rules: [
|
152 | {
|
153 | test: /\.worker\.(c|m)?js$/i,
|
154 | loader: "worker-loader",
|
155 | options: {
|
156 | publicPath: "/scripts/workers/",
|
157 | },
|
158 | },
|
159 | ],
|
160 | },
|
161 | };
|
162 | ```
|
163 |
|
164 | #### `Function`
|
165 |
|
166 | **webpack.config.js**
|
167 |
|
168 | ```js
|
169 | module.exports = {
|
170 | module: {
|
171 | rules: [
|
172 | {
|
173 | test: /\.worker\.(c|m)?js$/i,
|
174 | loader: "worker-loader",
|
175 | options: {
|
176 | publicPath: (pathData, assetInfo) => {
|
177 | return `/scripts/${pathData.hash}/workers/`;
|
178 | },
|
179 | },
|
180 | },
|
181 | ],
|
182 | },
|
183 | };
|
184 | ```
|
185 |
|
186 | ### `filename`
|
187 |
|
188 | Type: `String|Function`
|
189 | Default: based on `output.filename`, adding `worker` suffix, for example - `output.filename: '[name].js'` value of this option will be `[name].worker.js`
|
190 |
|
191 | The filename of entry chunks for web workers.
|
192 |
|
193 | #### `String`
|
194 |
|
195 | **webpack.config.js**
|
196 |
|
197 | ```js
|
198 | module.exports = {
|
199 | module: {
|
200 | rules: [
|
201 | {
|
202 | test: /\.worker\.(c|m)?js$/i,
|
203 | loader: "worker-loader",
|
204 | options: {
|
205 | filename: "[name].[contenthash].worker.js",
|
206 | },
|
207 | },
|
208 | ],
|
209 | },
|
210 | };
|
211 | ```
|
212 |
|
213 | #### `Function`
|
214 |
|
215 | **webpack.config.js**
|
216 |
|
217 | ```js
|
218 | module.exports = {
|
219 | module: {
|
220 | rules: [
|
221 | {
|
222 | test: /\.worker\.(c|m)?js$/i,
|
223 | loader: "worker-loader",
|
224 | options: {
|
225 | filename: (pathData) => {
|
226 | if (
|
227 | /\.worker\.(c|m)?js$/i.test(pathData.chunk.entryModule.resource)
|
228 | ) {
|
229 | return "[name].custom.worker.js";
|
230 | }
|
231 |
|
232 | return "[name].js";
|
233 | },
|
234 | },
|
235 | },
|
236 | ],
|
237 | },
|
238 | };
|
239 | ```
|
240 |
|
241 | ### `chunkFilename`
|
242 |
|
243 | Type: `String`
|
244 | Default: based on `output.chunkFilename`, adding `worker` suffix, for example - `output.chunkFilename: '[id].js'` value of this option will be `[id].worker.js`
|
245 |
|
246 | The filename of non-entry chunks for web workers.
|
247 |
|
248 | **webpack.config.js**
|
249 |
|
250 | ```js
|
251 | module.exports = {
|
252 | module: {
|
253 | rules: [
|
254 | {
|
255 | test: /\.worker\.(c|m)?js$/i,
|
256 | loader: "worker-loader",
|
257 | options: {
|
258 | chunkFilename: "[id].[contenthash].worker.js",
|
259 | },
|
260 | },
|
261 | ],
|
262 | },
|
263 | };
|
264 | ```
|
265 |
|
266 | ### `inline`
|
267 |
|
268 | Type: `'fallback' | 'no-fallback'`
|
269 | Default: `undefined`
|
270 |
|
271 | Allow to inline the worker as a `BLOB`.
|
272 |
|
273 | Inline mode with the `fallback` value will create file for browsers without support web workers, to disable this behavior just use `no-fallback` value.
|
274 |
|
275 | **webpack.config.js**
|
276 |
|
277 | ```js
|
278 | module.exports = {
|
279 | module: {
|
280 | rules: [
|
281 | {
|
282 | test: /\.worker\.(c|m)?js$/i,
|
283 | loader: "worker-loader",
|
284 | options: {
|
285 | inline: "fallback",
|
286 | },
|
287 | },
|
288 | ],
|
289 | },
|
290 | };
|
291 | ```
|
292 |
|
293 | ### `esModule`
|
294 |
|
295 | Type: `Boolean`
|
296 | Default: `true`
|
297 |
|
298 | By default, `worker-loader` generates JS modules that use the ES modules syntax.
|
299 |
|
300 | You can enable a CommonJS modules syntax using:
|
301 |
|
302 | **webpack.config.js**
|
303 |
|
304 | ```js
|
305 | module.exports = {
|
306 | module: {
|
307 | rules: [
|
308 | {
|
309 | test: /\.worker\.(c|m)?js$/i,
|
310 | loader: "worker-loader",
|
311 | options: {
|
312 | esModule: false,
|
313 | },
|
314 | },
|
315 | ],
|
316 | },
|
317 | };
|
318 | ```
|
319 |
|
320 | ## Examples
|
321 |
|
322 | ### Basic
|
323 |
|
324 | The worker file can import dependencies just like any other file:
|
325 |
|
326 | **index.js**
|
327 |
|
328 | ```js
|
329 | import Worker from "./my.worker.js";
|
330 |
|
331 | var worker = new Worker();
|
332 |
|
333 | var result;
|
334 |
|
335 | worker.onmessage = function (event) {
|
336 | if (!result) {
|
337 | result = document.createElement("div");
|
338 | result.setAttribute("id", "result");
|
339 |
|
340 | document.body.append(result);
|
341 | }
|
342 |
|
343 | result.innerText = JSON.stringify(event.data);
|
344 | };
|
345 |
|
346 | const button = document.getElementById("button");
|
347 |
|
348 | button.addEventListener("click", function () {
|
349 | worker.postMessage({ postMessage: true });
|
350 | });
|
351 | ```
|
352 |
|
353 | **my.worker.js**
|
354 |
|
355 | ```js
|
356 | onmessage = function (event) {
|
357 | var workerResult = event.data;
|
358 |
|
359 | workerResult.onmessage = true;
|
360 |
|
361 | postMessage(workerResult);
|
362 | };
|
363 | ```
|
364 |
|
365 | **webpack.config.js**
|
366 |
|
367 | ```js
|
368 | module.exports = {
|
369 | module: {
|
370 | rules: [
|
371 | {
|
372 | test: /\.worker\.(c|m)?js$/i,
|
373 | loader: "worker-loader",
|
374 | options: {
|
375 | esModule: false,
|
376 | },
|
377 | },
|
378 | ],
|
379 | },
|
380 | };
|
381 | ```
|
382 |
|
383 | ### Integrating with ES6+ features
|
384 |
|
385 | You can even use ES6+ features if you have the [`babel-loader`](https://github.com/babel/babel-loader) configured.
|
386 |
|
387 | **index.js**
|
388 |
|
389 | ```js
|
390 | import Worker from "./my.worker.js";
|
391 |
|
392 | const worker = new Worker();
|
393 |
|
394 | let result;
|
395 |
|
396 | worker.onmessage = (event) => {
|
397 | if (!result) {
|
398 | result = document.createElement("div");
|
399 | result.setAttribute("id", "result");
|
400 |
|
401 | document.body.append(result);
|
402 | }
|
403 |
|
404 | result.innerText = JSON.stringify(event.data);
|
405 | };
|
406 |
|
407 | const button = document.getElementById("button");
|
408 |
|
409 | button.addEventListener("click", () => {
|
410 | worker.postMessage({ postMessage: true });
|
411 | });
|
412 | ```
|
413 |
|
414 | **my.worker.js**
|
415 |
|
416 | ```js
|
417 | onmessage = function (event) {
|
418 | const workerResult = event.data;
|
419 |
|
420 | workerResult.onmessage = true;
|
421 |
|
422 | postMessage(workerResult);
|
423 | };
|
424 | ```
|
425 |
|
426 | **webpack.config.js**
|
427 |
|
428 | ```js
|
429 | module.exports = {
|
430 | module: {
|
431 | rules: [
|
432 | {
|
433 | test: /\.worker\.(c|m)?js$/i,
|
434 | use: [
|
435 | {
|
436 | loader: "worker-loader",
|
437 | },
|
438 | {
|
439 | loader: "babel-loader",
|
440 | options: {
|
441 | presets: ["@babel/preset-env"],
|
442 | },
|
443 | },
|
444 | ],
|
445 | },
|
446 | ],
|
447 | },
|
448 | };
|
449 | ```
|
450 |
|
451 | ### Integrating with TypeScript
|
452 |
|
453 | To integrate with TypeScript, you will need to define a custom module for the exports of your worker.
|
454 |
|
455 | **typings/worker-loader.d.ts**
|
456 |
|
457 | ```typescript
|
458 | declare module "worker-loader!*" {
|
459 | // You need to change `Worker`, if you specified a different value for the `workerType` option
|
460 | class WebpackWorker extends Worker {
|
461 | constructor();
|
462 | }
|
463 |
|
464 | // Uncomment this if you set the `esModule` option to `false`
|
465 | // export = WebpackWorker;
|
466 | export default WebpackWorker;
|
467 | }
|
468 | ```
|
469 |
|
470 | **my.worker.ts**
|
471 |
|
472 | ```typescript
|
473 | const ctx: Worker = self as any;
|
474 |
|
475 | // Post data to parent thread
|
476 | ctx.postMessage({ foo: "foo" });
|
477 |
|
478 | // Respond to message from parent thread
|
479 | ctx.addEventListener("message", (event) => console.log(event));
|
480 | ```
|
481 |
|
482 | **index.ts**
|
483 |
|
484 | ```typescript
|
485 | import Worker from "worker-loader!./Worker";
|
486 |
|
487 | const worker = new Worker();
|
488 |
|
489 | worker.postMessage({ a: 1 });
|
490 | worker.onmessage = (event) => {};
|
491 |
|
492 | worker.addEventListener("message", (event) => {});
|
493 | ```
|
494 |
|
495 | ### Cross-Origin Policy
|
496 |
|
497 | [`WebWorkers`](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) are restricted by a [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy), so if your `webpack` assets are not being served from the same origin as your application, their download may be blocked by your browser.
|
498 | This scenario can commonly occur if you are hosting your assets under a CDN domain.
|
499 | Even downloads from the `webpack-dev-server` could be blocked.
|
500 |
|
501 | There are two workarounds:
|
502 |
|
503 | Firstly, you can inline the worker as a blob instead of downloading it as an external script via the [`inline`](#inline) parameter
|
504 |
|
505 | **App.js**
|
506 |
|
507 | ```js
|
508 | import Worker from "./file.worker.js";
|
509 | ```
|
510 |
|
511 | **webpack.config.js**
|
512 |
|
513 | ```js
|
514 | module.exports = {
|
515 | module: {
|
516 | rules: [
|
517 | {
|
518 | loader: "worker-loader",
|
519 | options: { inline: "fallback" },
|
520 | },
|
521 | ],
|
522 | },
|
523 | };
|
524 | ```
|
525 |
|
526 | Secondly, you may override the base download URL for your worker script via the [`publicPath`](#publicpath) option
|
527 |
|
528 | **App.js**
|
529 |
|
530 | ```js
|
531 | // This will cause the worker to be downloaded from `/workers/file.worker.js`
|
532 | import Worker from "./file.worker.js";
|
533 | ```
|
534 |
|
535 | **webpack.config.js**
|
536 |
|
537 | ```js
|
538 | module.exports = {
|
539 | module: {
|
540 | rules: [
|
541 | {
|
542 | loader: "worker-loader",
|
543 | options: { publicPath: "/workers/" },
|
544 | },
|
545 | ],
|
546 | },
|
547 | };
|
548 | ```
|
549 |
|
550 | ## Contributing
|
551 |
|
552 | Please take a moment to read our contributing guidelines if you haven't yet done so.
|
553 |
|
554 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
|
555 |
|
556 | ## License
|
557 |
|
558 | [MIT](./LICENSE)
|
559 |
|
560 | [npm]: https://img.shields.io/npm/v/worker-loader.svg
|
561 | [npm-url]: https://npmjs.com/package/worker-loader
|
562 | [node]: https://img.shields.io/node/v/worker-loader.svg
|
563 | [node-url]: https://nodejs.org
|
564 | [deps]: https://david-dm.org/webpack-contrib/worker-loader.svg
|
565 | [deps-url]: https://david-dm.org/webpack-contrib/worker-loader
|
566 | [tests]: https://github.com/webpack-contrib/worker-loader/workflows/worker-loader/badge.svg
|
567 | [tests-url]: https://github.com/webpack-contrib/worker-loader/actions
|
568 | [cover]: https://codecov.io/gh/webpack-contrib/worker-loader/branch/master/graph/badge.svg
|
569 | [cover-url]: https://codecov.io/gh/webpack-contrib/worker-loader
|
570 | [chat]: https://badges.gitter.im/webpack/webpack.svg
|
571 | [chat-url]: https://gitter.im/webpack/webpack
|
572 | [size]: https://packagephobia.now.sh/badge?p=worker-loader
|
573 | [size-url]: https://packagephobia.now.sh/result?p=worker-loader
|