esbuild: Compressing JavaScript harder with Terser

Posted . Visible to the public.

esbuild Show archive.org snapshot comes with a minifier that is good enough for most cases. If you're looking to squeeze out as many bytes as possible, you can consider compressing with Terser instead.

Using Terser will increase your build times significantly, but produce the smallest output:

Terser (3 pass) Terser (1 pass) esbuild
application.js 163.6 kB 163.7 kB 181.6 kB
application.js (gzipped) 54.7 kB 54.9 kB 58.2 kB
Build time 5.2 s 4.7s 3.1 s

Installation

Add terser to your package.json.

Define a terserPlugin() in your esbuild.config.js:

const TERSER_NAME_CACHE = {}
const DEFAULT_TERSER_OPTIONS = {
  compress: { // https://github.com/terser/terser#compress-options
    passes: 3,
  },
  mangle: { // https://github.com/terser/terser#mangle-options
    properties: {
      regex: /^[_#]/ // https://makandracards.com/makandra/608582
    }
  },
  ecma: 2021,
  nameCache: TERSER_NAME_CACHE, // preserve renames across files
}


function terserPlugin(terserOptions = DEFAULT_TERSER_OPTIONS) {
  return {
    name: 'terserPlugin',
    setup(build) {
      build.onLoad({ filter: /\.js$/ }, async (args) => {
        const text = await fs.promises.readFile(args.path, "utf8")
        let { code, map } = await terser.minify(text, terserOptions)
        return {
          contents: code,
          loader: 'js',
        }
      })
    }
  }
}

Use the plugin in your build() or context() options:

esbuild.build({
  entrypoints: [...],
  minify: true, // prevent esbuild from pretty-printing output
  plugins: [
    ...,
    terserPlugin(),
  ]
})
Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2024-10-07 10:10)