From 6aa1eb0e9bae2628e66458b18805a1ec5961272a Mon Sep 17 00:00:00 2001 From: Evilebot Tnawi Date: Sat, 1 Aug 2020 15:15:40 +0300 Subject: [PATCH] docs: improve (#275) --- README.md | 335 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 281 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 6d4b541..e197577 100644 --- a/README.md +++ b/README.md @@ -66,12 +66,25 @@ And run `webpack` via your preferred method. ## Options -### `fallback` +| Name | Type | Default | Description | +| :-----------------------------------: | :--------------------------: | :-----------------------------: | :-------------------------------------------------------------------------------- | +| **[`worker`](#worker)** | `{String\|Object}` | `Worker` | Allows to set web worker constructor name and options | +| **[`publicPath`](#publicpath)** | `{String\|Function}` | based on `output.publicPath` | specifies the public URL address of the output files when referenced in a browser | +| **[`filename`](#filename)** | `{String\|Function}` | based on `output.filename` | The filename of entry chunks for web workers | +| **[`chunkFilename`](#chunkfilename)** | `{String}` | based on `output.chunkFilename` | The filename of non-entry chunks for web workers | +| **[`inline`](#inline)** | `'no-fallback' | 'fallback'` | `undefined` | Allow to inline the worker as a `BLOB` | +| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax | + +### `worker` + +Type: `String|Object` +Default: `Worker` -Type: `Boolean` -Default: `false` +Set the worker type. + +#### `String` -Require a fallback for non-worker supporting environments. +Allows to set web worker constructor name. **webpack.config.js** @@ -80,21 +93,55 @@ module.exports = { module: { rules: [ { - test: /\.worker\.js$/, - use: { loader: 'worker-loader' }, - options: { fallback: true }, + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + worker: 'SharedWorker', + }, }, ], }, }; ``` -### `inline` +#### `Object` -Type: `Boolean` -Default: `false` +Allow to set web worker constructor name and options. -You can also inline the worker as a BLOB with the `inline` parameter. +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + worker: { + type: 'SharedWorker', + options: { + type: 'classic', + credentials: 'omit', + name: 'my-custom-worker-name', + }, + }, + }, + }, + ], + }, +}; +``` + +### `publicPath` + +Type: `String|Function` +Default: based on `output.publicPath` + +The `publicPath` specifies the public URL address of the output files when referenced in a browser. +If not specified, the same public path used for other webpack assets is used. + +#### `String` **webpack.config.js** @@ -103,16 +150,18 @@ module.exports = { module: { rules: [ { - test: /\.worker\.js$/, - use: { loader: 'worker-loader' }, - options: { inline: true }, + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + publicPath: '/scripts/workers/', + }, }, ], }, }; ``` -_Note: Inline mode will also create chunks for browsers without support for inline workers, to disable this behavior just set `fallback` parameter as `false`._ +#### `Function` **webpack.config.js** @@ -121,22 +170,47 @@ module.exports = { module: { rules: [ { + test: /\.worker\.(c|m)?js$/i, loader: 'worker-loader', - options: { inline: true, fallback: false }, + options: { + publicPath: (pathData, assetInfo) => { + return `/scripts/${pathData.hash}/workers/`; + }, + }, }, ], }, }; ``` -### `name` +### `filename` -Type: `String` -Default: `[hash].worker.js` +Type: `String|Function` +Default: based on `output.filename`, adding `worker` suffix, for example - `output.filename: '[name].js'` value of this option will be `[name].worker.js` + +The filename of entry chunks for web workers. + +#### `String` + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + filename: '[name].[contenthash].worker.js', + }, + }, + ], + }, +}; +``` -To set a custom name for the output script, use the `name` parameter. -The name may contain the string `[hash]`, which will be replaced with a content dependent hash for caching purposes. -When using `name` alone `[hash]` is omitted. +#### `Function` **webpack.config.js** @@ -145,21 +219,31 @@ module.exports = { module: { rules: [ { + test: /\.worker\.(c|m)?js$/i, loader: 'worker-loader', - options: { name: 'WorkerName.[hash].js' }, + options: { + filename: (pathData) => { + if ( + /\.worker\.(c|m)?js$/i.test(pathData.chunk.entryModule.resource) + ) { + return '[name].custom.worker.js'; + } + + return '[name].js'; + }, + }, }, ], }, }; ``` -### publicPath +### `chunkFilename` Type: `String` -Default: `null` +Default: based on `output.chunkFilename`, adding `worker` suffix, for example - `output.chunkFilename: '[id].js'` value of this option will be `[id].worker.js` -Overrides the path from which worker scripts are downloaded. -If not specified, the same public path used for other webpack assets is used. +The filename of non-entry chunks for web workers. **webpack.config.js** @@ -168,20 +252,70 @@ module.exports = { module: { rules: [ { + test: /\.worker\.(c|m)?js$/i, loader: 'worker-loader', - options: { publicPath: '/scripts/workers/' }, + options: { + chunkFilename: '[id].[contenthash].worker.js', + }, }, ], }, }; ``` -### workerType +### `inline` -Type: `string` -Default: `Worker` +Type: `'fallback' | 'no-fallback'` +Default: `undefined` + +Allow to inline the worker as a `BLOB`. + +Inline mode with the `fallback` value will create file for browsers without support web workers, to disable this behavior just use `no-fallback` value. + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + inline: 'fallback', + }, + }, + ], + }, +}; +``` + +### `esModule` + +Type: `Boolean` +Default: `true` + +By default, `worker-loader` generates JS modules that use the ES modules syntax. + +You can enable a CommonJS modules syntax using: -Set the worker type. Defaults to `Worker`. Supports `ServiceWorker`, `SharedWorker`. +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + esModule: false, + }, + }, + ], + }, +}; +``` ## Examples @@ -189,59 +323,151 @@ Set the worker type. Defaults to `Worker`. Supports `ServiceWorker`, `SharedWork The worker file can import dependencies just like any other file: -**Worker.js** +**index.js** ```js -const _ = require('lodash'); +import Worker from './my.worker.js'; -const obj = { foo: 'foo' }; +var worker = new Worker(); -_.has(obj, 'foo'); +var result; -// Post data to parent thread -self.postMessage({ foo: 'foo' }); +worker.onmessage = function (event) { + if (!result) { + result = document.createElement('div'); + result.setAttribute('id', 'result'); -// Respond to message from parent thread -self.addEventListener('message', (event) => console.log(event)); + document.body.append(result); + } + + result.innerText = JSON.stringify(event.data); +}; + +const button = document.getElementById('button'); + +button.addEventListener('click', function () { + worker.postMessage({ postMessage: true }); +}); +``` + +**my.worker.js** + +```js +onmessage = function (event) { + var workerResult = event.data; + + workerResult.onmessage = true; + + postMessage(workerResult); +}; +``` + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + loader: 'worker-loader', + options: { + esModule: false, + }, + }, + ], + }, +}; ``` -### Integrating with ES Modules +### Integrating with ES6+ features -_Note: You can even use ES2015 Modules if you have the [`babel-loader`](https://github.com/babel/babel-loader) configured._ +You can even use ES6+ features if you have the [`babel-loader`](https://github.com/babel/babel-loader) configured. -**Worker.js** +**index.js** ```js -import _ from 'lodash'; +import Worker from './my.worker.js'; -const obj = { foo: 'foo' }; +const worker = new Worker(); -_.has(obj, 'foo'); +let result; -// Post data to parent thread -self.postMessage({ foo: 'foo' }); +worker.onmessage = (event) => { + if (!result) { + result = document.createElement('div'); + result.setAttribute('id', 'result'); -// Respond to message from parent thread -self.addEventListener('message', (event) => console.log(event)); + document.body.append(result); + } + + result.innerText = JSON.stringify(event.data); +}; + +const button = document.getElementById('button'); + +button.addEventListener('click', () => { + worker.postMessage({ postMessage: true }); +}); +``` + +**my.worker.js** + +```js +onmessage = function (event) { + const workerResult = event.data; + + workerResult.onmessage = true; + + postMessage(workerResult); +}; +``` + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.worker\.(c|m)?js$/i, + use: [ + { + loader: 'worker-loader', + }, + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env'], + }, + }, + ], + }, + ], + }, +}; ``` ### Integrating with TypeScript -To integrate with TypeScript, you will need to define a custom module for the exports of your worker +To integrate with TypeScript, you will need to define a custom module for the exports of your worker. **typings/worker-loader.d.ts** ```typescript declare module 'worker-loader!*' { + // You need to change `Worker`, if you specified a different value for the `workerType` option class WebpackWorker extends Worker { constructor(); } + // Uncomment this if you set the `esModule` option to `false` + // export = WebpackWorker; export default WebpackWorker; } ``` -**Worker.ts** +**my.worker.ts** ```typescript const ctx: Worker = self as any; @@ -253,7 +479,7 @@ ctx.postMessage({ foo: 'foo' }); ctx.addEventListener('message', (event) => console.log(event)); ``` -**App.ts** +**index.ts** ```typescript import Worker from 'worker-loader!./Worker'; @@ -271,6 +497,7 @@ worker.addEventListener('message', (event) => {}); [`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. This scenario can commonly occur if you are hosting your assets under a CDN domain. Even downloads from the `webpack-dev-server` could be blocked. + There are two workarounds: Firstly, you can inline the worker as a blob instead of downloading it as an external script via the [`inline`](#inline) parameter @@ -289,7 +516,7 @@ module.exports = { rules: [ { loader: 'worker-loader', - options: { inline: true }, + options: { inline: 'fallback' }, }, ], },