Repository: webpack-contrib/compression-webpack-plugin (js)

Issue:
Incorrect Brotli example
<!--
  Issues are so 🔥

  If you remove or skip this template, you'll make the 🐼 sad and the mighty god
  of Github will appear and pile-drive the close button from a great height
  while making animal noises.

  👉🏽 Need support, advice, or help? Don't open an issue!
  Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

Documentation Is:

<!-- Please place an x (no spaces!) in all [ ] that apply -->

- [ ] Missing
- [x] Needed
- [x] Confusing
- [ ] Not Sure?

### Please Explain in Detail...
The Brotli examples in the README do not correctly set the `compressionOptions`. The `BROTLI_PARAM_QUALITY` parameter is the equivalent to zlib's `level` option in terms of functionality, but not naming.

### Your Proposal for Changes
1. Revise the examples to set the Brotli parameters correctly.

```js
const zlib = require('zlib');
...
compressionOptions: {
  params: {
    [zlib.constants.BROTLI_PARAM_QUALITY]: 11
  }
}
```

2. Update the note to be more clear about `BROTLI_PARAM_QUALITY` being functionally equivalent to `level`, but not syntactically. 

3. Update note regarding Node version as Brotli native support was backported to [Node 10.16](https://github.com/nodejs/node/pull/27681).

Pull request description:
fix setting compression level for brotliCompress
<!--
  HOLY CRAP a Pull Request. We ❤️ those!

  If you remove or skip this template, you'll make the 🐼 sad and the mighty god
  of Github will appear and pile-drive the close button from a great height
  while making animal noises.

  Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [X] **bugfix**
- [ ] new **feature**
- [ ] **code refactor**
- [X] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [X] **metadata update**

### Motivation / Use-Case

<!--
  Please explain the motivation or use-case for your change.
  What existing problem does the PR solve?
  If this PR addresses an issue, please link to the issue.
-->

Fixes #154.

### Breaking Changes

No

<!--
  If this PR introduces a breaking change, please describe the impact and a
  migration path for existing applications.
-->

### Additional Info

No

Patch:
diff --git a/README.md b/README.md
index eb737ca..662ddd2 100644
--- a/README.md
+++ b/README.md
@@ -40,18 +40,18 @@ And run `webpack` via your preferred method.
 
 ## Options
 
-|                        Name                         |                   Type                    |      Default      | Description                                                                                                   |
-| :-------------------------------------------------: | :---------------------------------------: | :---------------: | :------------------------------------------------------------------------------------------------------------ |
-|                 **[`test`](#test)**                 | `{String\|RegExp\|Array<String\|RegExp>}` |    `undefined`    | Include all assets that pass test assertion                                                                   |
-|              **[`include`](#include)**              | `{String\|RegExp\|Array<String\|RegExp>}` |    `undefined`    | Include all assets matching any of these conditions                                                           |
-|              **[`exclude`](#exclude)**              | `{String\|RegExp\|Array<String\|RegExp>}` |    `undefined`    | Exclude all assets matching any of these conditions                                                           |
-|            **[`algorithm`](#algorithm)**            |           `{String\|Function}`            |      `gzip`       | The compression algorithm/function                                                                            |
-|   **[`compressionOptions`](#compressionoptions)**   |                `{Object}`                 |  `{ level: 9 }`   | Compression options for `algorithm`                                                                           |
-|            **[`threshold`](#threshold)**            |                `{Number}`                 |        `0`        | Only assets bigger than this size are processed (in bytes)                                                    |
-|             **[`minRatio`](#minratio)**             |                `{Number}`                 |       `0.8`       | Only assets that compress better than this ratio are processed (`minRatio = Compressed Size / Original Size`) |
-|             **[`filename`](#filename)**             |           `{String\|Function}`            | `[path][base].gz` | The target asset filename                                                                                     |
-| **[`deleteOriginalAssets`](#deleteoriginalassets)** |                `{Boolean}`                |      `false`      | Whether to delete the original assets or not                                                                  |
-|                **[`cache`](#cache)**                |                `{Boolean}`                |      `true`       | Enable file caching                                                                                           |
+|                        Name                         |                   Type                    |                            Default                            | Description                                                                                                   |
+| :-------------------------------------------------: | :---------------------------------------: | :-----------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------ |
+|                 **[`test`](#test)**                 | `{String\|RegExp\|Array<String\|RegExp>}` |                          `undefined`                          | Include all assets that pass test assertion                                                                   |
+|              **[`include`](#include)**              | `{String\|RegExp\|Array<String\|RegExp>}` |                          `undefined`                          | Include all assets matching any of these conditions                                                           |
+|              **[`exclude`](#exclude)**              | `{String\|RegExp\|Array<String\|RegExp>}` |                          `undefined`                          | Exclude all assets matching any of these conditions                                                           |
+|            **[`algorithm`](#algorithm)**            |           `{String\|Function}`            |                            `gzip`                             | The compression algorithm/function                                                                            |
+|   **[`compressionOptions`](#compressionoptions)**   |                `{Object}`                 | maximum available compression level, for gzip: `{ level: 9 }` | Compression options for `algorithm`                                                                           |
+|            **[`threshold`](#threshold)**            |                `{Number}`                 |                              `0`                              | Only assets bigger than this size are processed (in bytes)                                                    |
+|             **[`minRatio`](#minratio)**             |                `{Number}`                 |                             `0.8`                             | Only assets that compress better than this ratio are processed (`minRatio = Compressed Size / Original Size`) |
+|             **[`filename`](#filename)**             |           `{String\|Function}`            |                       `[path][base].gz`                       | The target asset filename                                                                                     |
+| **[`deleteOriginalAssets`](#deleteoriginalassets)** |                `{Boolean}`                |                            `false`                            | Whether to delete the original assets or not                                                                  |
+|                **[`cache`](#cache)**                |                `{Boolean}`                |                            `true`                             | Enable file caching                                                                                           |
 
 ### `test`
 
@@ -401,8 +401,9 @@ module.exports = {
       algorithm: 'brotliCompress',
       test: /\.(js|css|html|svg)$/,
       compressionOptions: {
-        // zlib’s `level` option matches Brotli’s `BROTLI_PARAM_QUALITY` option.
-        level: 11,
+        params: {
+          [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
+        },
       },
       threshold: 10240,
       minRatio: 0.8,
@@ -412,7 +413,8 @@ module.exports = {
 };
 ```
 
-**Note** The `level` option matches `BROTLI_PARAM_QUALITY` [for Brotli-based streams](https://nodejs.org/api/zlib.html#zlib_for_brotli_based_streams)
+**Note** Brotli’s `BROTLI_PARAM_QUALITY` option is functionally equivalent to zlib’s `level` option.
+You can find all Brotli’s options in [the relevant part of the zlib module documentation](https://nodejs.org/api/zlib.html#zlib_class_brotlioptions).
 
 ### Multiple compressed versions of assets for different algorithm
 
@@ -435,7 +437,9 @@ module.exports = {
       algorithm: 'brotliCompress',
       test: /\.(js|css|html|svg)$/,
       compressionOptions: {
-        level: 11,
+        params: {
+          [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
+        },
       },
       threshold: 10240,
       minRatio: 0.8,
diff --git a/src/index.js b/src/index.js
index 22a6932..8363dd9 100644
--- a/src/index.js
+++ b/src/index.js
@@ -66,8 +66,27 @@ class CompressionPlugin {
         );
       }
 
+      const defaultCompressionOptions =
+        {
+          gzip: {
+            level: zlib.constants.Z_BEST_COMPRESSION,
+          },
+          deflate: {
+            level: zlib.constants.Z_BEST_COMPRESSION,
+          },
+          deflateRaw: {
+            level: zlib.constants.Z_BEST_COMPRESSION,
+          },
+          brotliCompress: {
+            params: {
+              [zlib.constants.BROTLI_PARAM_QUALITY]:
+                zlib.constants.BROTLI_MAX_QUALITY,
+            },
+          },
+        }[algorithm] || {};
+
       this.options.compressionOptions = {
-        ...{ level: 9 },
+        ...defaultCompressionOptions,
         ...this.options.compressionOptions,
       };
     }


Test patch:
diff --git a/test/compressionOptions-option.test.js b/test/compressionOptions-option.test.js
index b643b33..d803f4e 100644
--- a/test/compressionOptions-option.test.js
+++ b/test/compressionOptions-option.test.js
@@ -44,4 +44,44 @@ describe('"compressionOptions" option', () => {
     expect(getWarnings(stats)).toMatchSnapshot('warnings');
     expect(getErrors(stats)).toMatchSnapshot('errors');
   });
+
+  it('set default compression level to maximum for gzip', async () => {
+    const compressionPlugin = new CompressionPlugin({
+      algorithm: 'gzip',
+    });
+
+    expect(compressionPlugin).toHaveProperty('options.compressionOptions', {
+      level: 9,
+    });
+  });
+
+  it('set default compression level to maximum for deflate', async () => {
+    const compressionPlugin = new CompressionPlugin({
+      algorithm: 'deflate',
+    });
+
+    expect(compressionPlugin).toHaveProperty('options.compressionOptions', {
+      level: 9,
+    });
+  });
+
+  it('set default compression level to maximum for deflateRaw', async () => {
+    const compressionPlugin = new CompressionPlugin({
+      algorithm: 'deflateRaw',
+    });
+
+    expect(compressionPlugin).toHaveProperty('options.compressionOptions', {
+      level: 9,
+    });
+  });
+
+  it('set default compression level to maximum for brotli', async () => {
+    const compressionPlugin = new CompressionPlugin({
+      algorithm: 'brotliCompress',
+    });
+
+    expect(compressionPlugin).toHaveProperty('options.compressionOptions', {
+      params: { 1: 11 },
+    });
+  });
 });