# webbundle-webpack-plugin

> Webpack plugin to generate WebBundle output.

Latest version **0.2.0** (published 2024-07-10) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install webbundle-webpack-plugin
pnpm add webbundle-webpack-plugin
yarn add webbundle-webpack-plugin
bun add webbundle-webpack-plugin
```

## Health

**Score 35/100 (D)** — status: abandoned.

Positive: esm support; no vulnerabilities; high maintenance score.

Warnings: low downloads; no types; pre 1.0.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 0.2.0 |
| Published | 2024-07-10 |
| First published | 2020-02-04 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Node | >= 16.0.0 |
| Dependencies | 4 |
| Unpacked size | 63.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 64 |
| Author | Kunihiko Sakamoto |
| Maintainers | google-wombot, ksakamoto |
| Keywords | webpack, plugin, web-bundle, isolated-web-app |

## Links

- npm: https://www.npmjs.com/package/webbundle-webpack-plugin
- Repository: https://github.com/GoogleChromeLabs/webbundle-plugins
- Homepage: https://github.com/GoogleChromeLabs/webbundle-plugins#readme
- Issues: https://github.com/GoogleChromeLabs/webbundle-plugins/issues
- npm.io page: https://npm.io/package/webbundle-webpack-plugin

## Dependencies (4)

- [wbn](https://npm.io/package/wbn.md) 0.0.9
- [zod](https://npm.io/package/zod.md) ^3.21.4
- [mime](https://npm.io/package/mime.md) ^2.4.4
- [wbn-sign](https://npm.io/package/wbn-sign.md) 0.2.0

## Alternatives

- [raw-loader](https://npm.io/package/raw-loader.md) — 4.3M weekly downloads
- [plop](https://npm.io/package/plop.md) — 1.4M weekly downloads
- [webpack-deadcode-plugin](https://npm.io/package/webpack-deadcode-plugin.md) — 80.3K weekly downloads
- [@storybook/preact-vite](https://npm.io/package/@storybook/preact-vite.md) — 54.2K weekly downloads
- [vite-plugin-transform](https://npm.io/package/vite-plugin-transform.md) — 2.4K weekly downloads

## Recent versions

- 0.2.0 (latest) — 2024-07-10
- 0.1.5 — 2024-05-07
- 0.1.4 — 2024-01-03
- 0.1.3 — 2023-05-23
- 0.1.2 — 2023-05-17
- 0.1.1 — 2023-03-23
- 0.1.0 — 2023-03-13
- 0.0.4 — 2022-11-25
- 0.0.3 — 2022-10-18
- 0.0.2 — 2022-10-13
- 0.0.1 — 2021-02-25
- 0.0.0 — 2020-02-04

## README

# webbundle-webpack-plugin

A Webpack plugin which generates
[Web Bundles](https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html)
output. Currently the spec is still a draft, so this package is also in alpha
until the spec stabilizes.

## Requirements

This plugin requires Node v14.0.0+ and Webpack v4.0.1+.

## Install

Using npm:

```bash
npm install webbundle-webpack-plugin --save-dev
```

## Usage

### General Web Bundle

This example assumes your application entry point is `src/index.js` and static
files (including `index.html`) are located in `static` directory.

```js
/* webpack.config.js */
const path = require('path');
const WebBundlePlugin = require('webbundle-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.js',
  },
  plugins: [
    new WebBundlePlugin({
      baseURL: 'https://example.com/',
      static: { dir: path.resolve(__dirname, 'static') },
      output: 'example.wbn',
    }),
  ],
};
```

A WBN file `dist/example.wbn` should be written.

### [Isolated Web App](https://github.com/WICG/isolated-web-apps/blob/main/README.md) (Signed Web Bundle)

This example assumes your application entry point is `src/index.js`, static
files (including `index.html`) are located in `static` directory and you have a
`.env` file in the root directory with `ED25519KEY` defined in it. The example
also requires installing `dotenv` npm package as a dev dependency.

It is also required to have a
[Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) at
`/.well-known/manifest.webmanifest`, which can be placed e.g. in the `static`
directory.

Also as in the below example, `baseURL` must be of format
`isolated-app://${WEB_BUNDLE_ID}` for Isolated Web Apps. It can easily be
generated from the private key with `WebBundleId` helper class from `wbn-sign`
package. See
[Scheme explainer](https://github.com/WICG/isolated-web-apps/blob/main/Scheme.md)
for more details. Also note that providing `headerOverride` is optional.

```js
/* webpack.config.js */
const path = require('path');
const WebBundlePlugin = require('webbundle-webpack-plugin');
const {
  NodeCryptoSigningStrategy,
  parsePemKey,
  readPassphrase,
  WebBundleId,
} = require('wbn-sign');
require('dotenv').config({ path: './.env' });

module.exports = async () => {
  const key = parsePemKey(process.env.ENC_ED25519KEY, await readPassphrase());

  return {
    entry: './src/index.js',
    output: { path: path.resolve(__dirname, 'dist'), filename: 'app.js' },
    plugins: [
      new WebBundlePlugin({
        baseURL: new WebBundleId(key).serializeWithIsolatedWebAppOrigin(),
        static: { dir: path.resolve(__dirname, 'static') },
        output: 'signed.swbn',
        integrityBlockSign: {
          strategy: new NodeCryptoSigningStrategy(key),
        },
        headerOverride: {
          'cross-origin-embedder-policy': 'require-corp',
          'cross-origin-opener-policy': 'same-origin',
          'cross-origin-resource-policy': 'same-origin',
          'content-security-policy':
            "base-uri 'none'; default-src 'self'; object-src 'none'; frame-src 'self' https: blob: data:; connect-src 'self' https: wss:; script-src 'self' 'wasm-unsafe-eval'; img-src 'self' https: blob: data:; media-src 'self' https: blob: data:; font-src 'self' blob: data:; style-src 'self' 'unsafe-inline'; require-trusted-types-for 'script';",
        },
      }),
    ],
  };
};
```

A signed web bundle (containing an
[Integrity Block](https://github.com/WICG/webpackage/blob/main/explainers/integrity-signature.md))
should be written to `dist/signed.swbn`.

## Options

### `baseURL`

Type: `string`

Default: `''`

Specifies the URL prefix prepended to the file names in the bundle. Non-empty
baseURL must end with `/`.

### `primaryURL`

Type: `string`

Default: baseURL

Specifies the bundle's main resource URL.

### `static`

Type: `{ dir: String, baseURL?: string }`

If specified, files and subdirectories under `dir` will be added to the bundle.
The `baseURL` field can be omitted and defaults to `Options.baseURL`.

### `output`

Type: `string`

Default: `out.wbn`

Specifies the file name of the Web Bundle to emit.

### `formatVersion`

Type: `string`

Default: `b2`

Specifies WebBundle format version.

- version `b2` follows
  [the latest version of the Web Bundles spec](https://datatracker.ietf.org/doc/html/draft-yasskin-wpack-bundled-exchanges-04)
  (default).
- version `b1` follows
  [the previous version of the Web Bundles spec](https://datatracker.ietf.org/doc/html/draft-yasskin-wpack-bundled-exchanges-03).

### `integrityBlockSign`

Type:

- `{ key: KeyObject, isIwa?: boolean }`
- `{ strategy: ISigningStrategy, isIwa?: boolean }`
- `{ strategies: Array<ISigningStrategy>, webBundleId: string, isIwa?: boolean }`

Object specifying the signing options with
[Integrity Block](https://github.com/WICG/webpackage/blob/main/explainers/integrity-signature.md).

### `integrityBlockSign.key`

Note: Either this or `integrityBlockSign.strategy` is required when
`integrityBlockSign` is in place.

Type: `KeyObject`

An unencrypted ed25519 private key can be generated with:

```bash
openssl genpkey -algorithm Ed25519 -out ed25519key.pem
```

For better security, one should prefer using passphrase-encrypted ed25519
private keys. To encrypt an unencrypted private key, run:

```bash
# encrypt the key (will ask for a passphrase, make sure to use a strong one)
openssl pkcs8 -in ed25519key.pem -topk8 -out encrypted_ed25519key.pem

# delete the unencrypted key
rm ed25519key.pem
```

It can be parsed with an imported helper function `parsePemKey(...)` from
`wbn-sign` npm package. For an encrypted private key there's also an async
helper function (`readPassphrase()`) to prompt the user for the passphrase the
key was encrypted with.

```js
// For an unencrypted ed25519 key.
const key = parsePemKey(process.env.ED25519KEY);

// For an encrypted ed25519 key.
const key = parsePemKey(process.env.ENC_ED25519KEY, await readPassphrase());
```

Note that in order for the key to be parsed correctly, it must contain the
`BEGIN` and `END` headers and line breaks (`\n`). Below an example `.env` file:

```bash
ED25519KEY="-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIB8nP5PpWU7HiILHSfh5PYzb5GAcIfHZ+bw6tcd/LZXh\n-----END PRIVATE KEY-----"
```

### `integrityBlockSign.strategy`

Note: Either this or `integrityBlockSign.key` is required when
`integrityBlockSign` is in place.

Type: `ISigningStrategy`

Example web bundle plugin options using a signing strategy:

```js
const pluginOptionsWithPredefinedSigningStrategy = {
  // ...other plugin options here...
  integrityBlockSign: {
    strategy: new NodeCryptoSigningStrategy(privateKey),
  },
};

const pluginOptionsWithCustomSigningStrategy = {
  // ...other plugin options here...
  integrityBlockSign: {
    strategy: new (class /* implements ISigningStrategy */ {
      async sign(data) {
        /** E.g. connect to one's external signing service that signs the
         * payload. */
      }
      async getPublicKey() {
        /** E.g. connect to one's external signing service that returns the
         * public key. */
      }
    })(),
  },
};
```

### `integrityBlockSign.strategies`

Type: `Array<ISigningStrategy>`

Use this overload to sign a bundle with multiple keys. Note that `webBundleId`
must always be specified when using `strategies`.

```
const pluginOptionsWithMultipleStrategiesAndWebBundleId = {
  // ...other plugin options here...
  integrityBlockSign: {
    strategies: [
      new NodeCryptoSigningStrategy(privateKey1),
      new NodeCryptoSigningStrategy(privateKey2)
    ],
    webBundleId: "some-random-id"
  },
};
```

### `integrityBlockSign.webBundleId`

Type: `string`

Allows specifying a custom id for this signed web bundle to decouple it from the
signing keys. Must be used together with `strategies`.

### `integrityBlockSign.isIwa` (optional)

Type: `boolean`

Default: `true`

If `undefined` or `true`, enforces certain
[Isolated Web App](https://github.com/WICG/isolated-web-apps) -related checks
for the headers. Also adds default IWA headers if completely missing. If set to
`false`, skips validation checks and doesn't tamper with the headers.

### `headerOverride` (optional)

Type: `{ [key: string]: string; }` |
`(filepath: string) => { [key: string]: string; };`

Object of strings specifying overridden headers or a function returning the same
kind of object.

## Discuss & Help

For discussions related to this repository's content, the Web Bundle plugins for
webpack and rollup, please use
[GitHub Issues](https://github.com/GoogleChromeLabs/webbundle-plugins/issues).

If you'd like to discuss the Web Packaging proposal itself, consider opening an
issue in its incubation repository at https://github.com/WICG/webpackage.

For discussions related to Isolated Web Apps in general, or Chromium-specific
implementation and development questions, please use the
[iwa-dev@chromium.org](https://groups.google.com/a/chromium.org/g/iwa-dev)
mailing list.

If you'd like to discuss the Isolated Web Apps proposal, which builds on top of
Web Bundles, consider opening an issue in the incubation repository at
https://github.com/WICG/isolated-web-apps.

## Release Notes

### v0.2.0

- Add support for the v2 integrity block format. Now web-bundle-id is no longer
  presumed to be a derivative of the first public key in the stack, but rather
  acts as a separate entry in the integrity block attributes, and multiple
  independent signatures are allowed to facilitate key rotation.

### v0.1.5

- Add support for ECDSA P-256 SHA-256 signing algorithm
- Bumping underlying wbn-sign version to v0.1.3.

### v0.1.4

- Updates to style-src and wss CSP values.
- Bumping underlying wbn-sign version to v0.1.1.

### v0.1.3

- BUG: Async `integrityBlockSign.strategy` was not working correctly. Now with
  `tapPromise` instead of `tap` this is fixed.
  \[[#59](https://github.com/GoogleChromeLabs/webbundle-plugins/pull/59/)\]

### v0.1.2

- Add support for `integrityBlockSign.strategy` plugin option which can be used
  to pass one of the predefined strategies or one's own implementation class for
  ISigningStrategy. One can also use the old `integrityBlockSign.key` option,
  which defaults to the predefined `NodeCryptoSigningStrategy` strategy.
- Refactor plugin to be in TypeScript.
- Combine the Webpack and Rollup web bundle plugins to live in the same
  repository and share some duplicated code. Taking advantage of
  [npm workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces).

### v0.1.1

- Add support for overriding headers with an optional `headerOverride` plugin
  option.

### v0.1.0

- BREAKING CHANGE: Change type of integrityBlockSign.key to be KeyObject instead
  of string.

### v0.0.4

- Support for signing web bundles with
  [integrity block](https://github.com/WICG/webpackage/blob/main/explainers/integrity-signature.md)
  added.

## License

Licensed under the Apache-2.0 license.

## Contributing

See [CONTRIBUTING.md](../../CONTRIBUTING.md) file.

## Disclaimer

This is not an officially supported Google product.

---
_Source: https://npm.io/package/webbundle-webpack-plugin · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
