Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/googlechromelabs/worker-plugin

👩‍🏭 Adds native Web Worker bundling support to Webpack.
https://github.com/googlechromelabs/worker-plugin

web-worker webpack webpack-plugin webworker workers

Last synced: 3 days ago
JSON representation

👩‍🏭 Adds native Web Worker bundling support to Webpack.

Awesome Lists containing this project

README

        


worker-plugin


👩‍🏭 worker-plugin


Automatically bundle & compile Web Workers within Webpack.

### Features

Automatically compiles modules loaded in Web Workers:

```js
const worker = new Worker('./foo.js', { type: 'module' });
^^^^^^^^^^
gets bundled using webpack
```

The best part? That worker constructor works just fine without bundling turned on, but when bundled the result is **supported in all browsers** that support Web Workers - all the way back to IE 10!

Workers with fully dynamic URLs, Blob URLs, data URLs or with no `{ type:'module' }` option are left unchanged.

> _**Compatibility Note:** Webpack 5 now includes worker bundling. It uses a slightly different syntax:_

> _`new Worker(new URL("./my_worker.js", import.meta.url))`_

## Installation

```sh
npm install -D worker-plugin
```

Then drop it into your **webpack.config.js:**

```diff
+ const WorkerPlugin = require('worker-plugin');

module.exports = {
<...>
plugins: [
+ new WorkerPlugin()
]
<...>
}
```

> **Note:** If you're planning on having more than one worker, you'll need to make sure [`output.filename`](https://webpack.js.org/configuration/output/#outputfilename) is set to something dynamic, e.g. `"[name].bundle.js"` otherwise the generated filenames will overwrite one another.

## Usage

**worker.js**: _(our worker module)_

```js
// This is a module worker, so we can use imports (in the browser too!)
import { calculatePi } from './some-other-module';

addEventListener('message', event => {
postMessage(calculatePi(event.data));
});
```

**main.js**: _(our demo, on the main thread)_

```js
const piWorker = new Worker('./worker.js', { type: 'module' });
piWorker.onmessage = event => {
console.log('pi: ' + event.data);
};
piWorker.postMessage(42);
```

> **Note:** in order to ensure WorkerPlugin bundles your worker, make sure you're passing a **string** URL/filename to the Worker constructor. WorkerPlugin cannot bundle workers with dynamic/variable filenames, Blob or data URLs - it will leave them unmodified and print a warning during your build.

## Options

In most cases, no options are necessary to use WorkerPlugin.

### `globalObject` _(string | false)_

WorkerPlugin will print a warning if your Webpack configuration has `output.globalObject` set to `window`, since doing so breaks Hot Module Replacement in web workers.

If you're not using HMR and want to disable this warning, pass `globalObject:false`:

```js
new WorkerPlugin({
// disable warnings about "window" breaking HMR:
globalObject: false
})
```

To configure the value of `output.globalObject` for WorkerPlugin's internal Webpack Compiler, set `globalObject` to any String:

```js
new WorkerPlugin({
// use "self" as the global object when receiving hot updates.
globalObject: 'self' // <-- this is the default value
})
```

### `plugins` _(array)_

By default, WorkerPlugin doesn't run any of your configured Webpack plugins when bundling worker code - this avoids running things like `html-webpack-plugin` twice. For cases where it's necessary to apply a plugin to Worker code, use the `plugins` option.

Here you can specify the names of plugins to "copy" from your existing Webpack configuration, or provide specific plugins to apply only to worker code:

```js
module.exports = {
<...>
plugins: [
// an example of a plugin already being used:
new SomeExistingPlugin({ <...> }),

new WorkerPlugin({
plugins: [
// A string here will copy the named plugin from your configuration:
'SomeExistingPlugin',

// Or you can specify a plugin directly, only applied to Worker code:
new SomePluginToApplyOnlyToWorkers({ <...> })
]
})
]
<...>
}
```

### `sharedWorker` _(boolean)_

If set to `true`, this option enables the bundling of [SharedWorker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker):

```js
const shared = new SharedWorker('./my-shared-worker.js', { type: 'module' });
```

### `worker` _(boolean)_

If set to `false`, this option disables the bundling of [Worker]. Intended to be used with `{ sharedWorker: true }` to allow bundling of [SharedWorker] only without also bundling [Worker].

### `preserveTypeModule` _(boolean)_
### `workerType` _(string)_

Normally, WorkerPlugin will transform `new Worker('./a.js', { type: 'module' })` to completely remove the `type` option, outputting something like `new Worker('a.worker.js')`. This allows the plugin to compile Module Workers to Classic Workers, which are supported in all browsers.

To instead retain `{type:'module'}` in bundled output, set the `preserveTypeModule` option to `true`:

```js
plugins: [
new WorkerPlugin({
preserveTypeModule: true
})
]
```

Similarly, if you need to have WorkerPlugin output a specific `type` value, use the `workerType` option to specify it:

```js
plugins: [
new WorkerPlugin({
workerType: 'foo' // note: this isn't a thing!
})
]
```

## Loader

At its core, worker-plugin provides two features: parsing and handling of `new Worker()`, and standalone bundling of modules for use in a different JavaScript context.

If all you want is to compile separate bundles for a module, `worker-plugin/loader` provides the bundling functionality of worker-plugin as a standalone Webpack loader. This is useful for generating bundles for use in iframes, Service Workers or Worklets. Applying `worker-plugin/loader` to an import will bundle that module and return its URL:

```js
import workerUrl from 'worker-plugin/loader!./my-worker';

console.log(workerUrl); // "/0.worker.js"

CSS.paintWorklet.addModule(workerUrl);
```

Two options are available:

| Option | Type | Description
|---|---|:--|
| `name` | _string_ | Controls the name of the generated chunk.
The name is used to generate a URL according to `output.chunkFilename`.
| `esModule` | _boolean_ | Export the URL from an ES Module (`export default url`).
The default is CommonJS (`module.exports = url`).

Options can be supplied inline:

```js
import url from 'worker-plugin/loader?name=foo&esModule!./foo';
```

... or by setting up a loader alias:

```js
// webpack.config.js to enable this:
// import url from 'worker!./foo';
{
resolveLoader: {
alias: {
worker: 'worker-plugin/loader?esModule'
}
}
}
```

## License

Apache-2.0