aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/compressionPlugin.ts
blob: 8b347cf407d64be902f684bef9472d11ce98c308 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * Copyright (c) 2024 Kristóf Marussy <kristof@marussy.com>
 *
 * SPDX-License-Identifier: MIT
 */

import { readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { promisify } from 'node:util';
import zlib, { type BrotliOptions, type ZlibOptions } from 'node:zlib';

import pluginSitemap, { type PluginOptions } from '@docusaurus/plugin-sitemap';
import type { LoadContext, Plugin } from '@docusaurus/types';
import { Globby } from '@docusaurus/utils';
import CompressionPlugin from 'compression-webpack-plugin';

const gzipOptions = {
  level: 9,
} satisfies ZlibOptions;
const brotliOptions = {
  params: {
    [zlib.constants.BROTLI_PARAM_QUALITY]: 11,
  },
};
const test = /\.(js|css|svg|txt)$/;
const paths = ['**/*.html', 'robots.txt', 'sitemap.xml'];

const gzip = promisify(zlib.gzip);
const brotliCompress = promisify(zlib.brotliCompress);

export default function compressionPlugin(
  context: LoadContext,
  options: PluginOptions,
): Plugin<void> {
  const sitemap = pluginSitemap(context, options);
  return {
    name: 'marussy-compression-plugin',
    configureWebpack: (_config, isServer) =>
      isServer
        ? {}
        : {
            plugins: [
              new CompressionPlugin({
                test,
                filename: '[path][base].gz',
                compressionOptions: gzipOptions,
              }),
              new CompressionPlugin<BrotliOptions>({
                test,
                filename: '[path][base].br',
                algorithm: 'brotliCompress',
                compressionOptions: brotliOptions,
              }),
            ],
          },
    async postBuild(props) {
      await sitemap?.postBuild(props);
      const files = await Globby(paths.map((s) => path.join(props.outDir, s)));
      for (const file of files) {
        console.log(file);
        const contents = await readFile(file);
        const gzipContents = await gzip(contents, gzipOptions);
        await writeFile(`${file}.gz`, gzipContents);
        const brotliContents = await brotliCompress(contents, brotliOptions);
        await writeFile(`${file}.br`, brotliContents);
      }
    },
  };
}

export { validateOptions } from '@docusaurus/plugin-sitemap';