Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@
"nocheck",
"dont",
"doctype",
"wilsonzlin"
"wilsonzlin",
"cssnano",
"csso",
"lightningcss",
"sourcefile",
"stringifier",
"sourcesContent"
],
"ignorePaths": [
"CHANGELOG.md",
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ jobs:
name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x, 22.x, 24.x]
Expand Down Expand Up @@ -109,6 +110,14 @@ jobs:
run: npm ci
if: matrix.node-version != '10.x' && matrix.node-version != '12.x' && matrix.node-version != '14.x' && matrix.node-version != '16.x' && matrix.node-version != '18.x'

- name: Install older cssnano (Node 10/12)
if: matrix.node-version == '10.x' || matrix.node-version == '12.x'
run: npm install -D --no-save cssnano@^5 --force

- name: Install older cssnano (Node 14/16)
if: matrix.node-version == '14.x' || matrix.node-version == '16.x'
run: npm install -D --no-save cssnano@^6 --force

- name: Install webpack ${{ matrix.webpack-version }}
if: matrix.webpack-version != 'latest'
run: npm i webpack@${{ matrix.webpack-version }}
Expand Down
253 changes: 251 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
# terser-webpack-plugin

This plugin minifies your assets in a webpack build. It ships with several
built-in minimizers covering JavaScript, JSON, and HTML — pick one with the
[`minify`](#minify) option and target the right files with [`test`](#test).
built-in minimizers covering JavaScript, JSON, HTML, and CSS — pick one
with the [`minify`](#minify) option and target the right files with
[`test`](#test).

JavaScript minimizers:

Expand All @@ -34,6 +35,15 @@ HTML minimizers:
- [`@swc/html`](https://github.com/swc-project/swc) — `TerserPlugin.swcMinifyHtml` (full HTML documents) and `TerserPlugin.swcMinifyHtmlFragment` (HTML fragments, e.g. `<template>` content). Very fast Rust-based platform for the Web. Requires `npm install --save-dev @swc/html`.
- [`@minify-html/node`](https://github.com/wilsonzlin/minify-html) — `TerserPlugin.minifyHtmlNode`. A Rust HTML minifier optimised for speed and effectiveness. Requires `npm install --save-dev @minify-html/node`.

CSS minimizers:

- [`cssnano`](https://cssnano.github.io/cssnano/) — `TerserPlugin.cssnanoMinify`. The default CSS minimizer. Built on top of [PostCSS](https://postcss.org/). Requires `npm install --save-dev cssnano postcss`.
- [`csso`](https://github.com/css/csso) — `TerserPlugin.cssoMinify`. A CSS minifier with structural optimisations. Requires `npm install --save-dev csso`.
- [`clean-css`](https://github.com/clean-css/clean-css) — `TerserPlugin.cleanCssMinify`. A widely-used CSS optimiser. Requires `npm install --save-dev clean-css`.
- [`esbuild`](https://github.com/evanw/esbuild) — `TerserPlugin.esbuildMinifyCss`. Very fast CSS minification using esbuild's CSS loader. Requires `npm install --save-dev esbuild`.
- [`lightningcss`](https://github.com/parcel-bundler/lightningcss) — `TerserPlugin.lightningCssMinify`. A Rust-based CSS parser, transformer, and minifier. Requires `npm install --save-dev lightningcss`.
- [`@swc/css`](https://github.com/swc-project/swc) — `TerserPlugin.swcMinifyCss`. A very fast Rust-based CSS minifier. Requires `npm install --save-dev @swc/css`.

All of the non-default minimizers are declared as **optional** peer
dependencies — install only the ones you actually use. You can also stack
multiple `TerserPlugin` instances in the same build to handle different
Expand Down Expand Up @@ -1065,6 +1075,196 @@ module.exports = {

You can also stack multiple `TerserPlugin` instances to compress different files with different `minify` functions in the same build (e.g. JS with `terserMinify`, HTML with `htmlMinifierTerser`, JSON with `jsonMinify`).

### CSS

The plugin can minify CSS assets too. Pick one of the bundled CSS
minimizers and set `test` to match your CSS files.

Available CSS minimizers:

- `TerserPlugin.cssnanoMinify` — uses [`cssnano`](https://cssnano.github.io/cssnano/) (via [`postcss`](https://postcss.org/)).
- `TerserPlugin.cssoMinify` — uses [`csso`](https://github.com/css/csso).
- `TerserPlugin.cleanCssMinify` — uses [`clean-css`](https://github.com/clean-css/clean-css).
- `TerserPlugin.esbuildMinifyCss` — uses [`esbuild`](https://github.com/evanw/esbuild) with the CSS loader.
- `TerserPlugin.lightningCssMinify` — uses [`lightningcss`](https://github.com/parcel-bundler/lightningcss).
- `TerserPlugin.swcMinifyCss` — uses [`@swc/css`](https://github.com/swc-project/swc).

The CSS minimizers are optional peer dependencies — install only the ones
you actually use:

```console
npm install --save-dev cssnano postcss
# or
npm install --save-dev csso
# or
npm install --save-dev clean-css
# or
npm install --save-dev esbuild
# or
npm install --save-dev lightningcss
# or
npm install --save-dev @swc/css
```

> **Note**
>
> CSS assets typically come from plugins like
> [`mini-css-extract-plugin`](https://github.com/webpack-contrib/mini-css-extract-plugin)
> or webpack's [asset modules](https://webpack.js.org/guides/asset-modules/).

#### `cssnano`

[`cssnano`](https://cssnano.github.io/cssnano/) is the default CSS minimizer. It runs as a [PostCSS](https://postcss.org/) plugin.

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
// Keeps the default Terser plugin for JS files
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cssnanoMinify,
// Options - https://cssnano.github.io/cssnano/docs/config-file/
minimizerOptions: {
preset: "default",
},
}),
],
},
};
```

#### `csso`

[`csso`](https://github.com/css/csso) is a CSS minifier with structural optimisations.

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cssoMinify,
// Options - https://github.com/css/csso#minifysource-options
minimizerOptions: {},
}),
],
},
};
```

#### `clean-css`

[`clean-css`](https://github.com/clean-css/clean-css) is a widely-used CSS optimiser.

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cleanCssMinify,
// Options - https://github.com/clean-css/clean-css#constructor-options
minimizerOptions: {},
}),
],
},
};
```

#### `esbuild`

[`esbuild`](https://github.com/evanw/esbuild) ships with a fast CSS minifier (used via its CSS loader).

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.esbuildMinifyCss,
// Options - https://esbuild.github.io/api/#transform-api
minimizerOptions: {},
}),
],
},
};
```

#### `lightningcss`

[`lightningcss`](https://github.com/parcel-bundler/lightningcss) is a Rust-based CSS parser, transformer, and minifier.

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.lightningCssMinify,
// Options - https://lightningcss.dev/transpilation.html
minimizerOptions: {},
}),
],
},
};
```

#### `@swc/css`

[`@swc/css`](https://github.com/swc-project/swc) is a Rust-based CSS minifier.

**webpack.config.js**

```js
const TerserPlugin = require("terser-webpack-plugin");

module.exports = {
optimization: {
minimize: true,
minimizer: [
"...",
new TerserPlugin({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.swcMinifyCss,
// Options - https://github.com/swc-project/bindings/blob/main/packages/css/index.ts
minimizerOptions: {},
}),
],
},
};
```

### Custom Minify Function

Override the default minify function - use `uglify-js` for minification.
Expand Down Expand Up @@ -1120,12 +1320,17 @@ With built-in minify functions:

```ts
import { type JsMinifyOptions as SwcOptions } from "@swc/core";
import { type MinifyOptions as SwcCssOptions } from "@swc/css";
import {
type FragmentOptions as SwcHtmlFragmentOptions,
type Options as SwcHtmlOptions,
} from "@swc/html";
import { type OptionsOutput as CleanCssOptions } from "clean-css";
import { type Options as CssnanoOptions } from "cssnano";
import { type CompressOptions as CssoOptions } from "csso";
import { type TransformOptions as EsbuildOptions } from "esbuild";
import { type Options as HtmlMinifierTerserOptions } from "html-minifier-terser";
import { type TransformOptions as LightningCssOptions } from "lightningcss";
import { type MinifyOptions as TerserOptions } from "terser";
import { type MinifyOptions as UglifyJSOptions } from "uglify-js";

Expand Down Expand Up @@ -1182,6 +1387,50 @@ module.exports = {
// `@swc/html` fragment options
},
}),

// CSS minimizers
new TerserPlugin<CssnanoOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cssnanoMinify,
minimizerOptions: {
// `cssnano` options
},
}),
new TerserPlugin<CssoOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cssoMinify,
minimizerOptions: {
// `csso` options
},
}),
new TerserPlugin<CleanCssOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.cleanCssMinify,
minimizerOptions: {
// `clean-css` options
},
}),
new TerserPlugin<EsbuildOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.esbuildMinifyCss,
minimizerOptions: {
// `esbuild` options (CSS loader)
},
}),
new TerserPlugin<LightningCssOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.lightningCssMinify,
minimizerOptions: {
// `lightningcss` options
},
}),
new TerserPlugin<SwcCssOptions>({
test: /\.css(\?.*)?$/i,
minify: TerserPlugin.swcMinifyCss,
minimizerOptions: {
// `@swc/css` options
},
}),
],
},
};
Expand Down
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
// The bundled CSS minimizers (`cssnano@7`, `@swc/css`, `lightningcss`,
// `esbuild@0.27`) require modern Node and don't reliably install on the
// Windows agents. Skip the dedicated CSS test file outright on rows that
// can't run them so we don't end up with stale or missing snapshots.
const NODE_MAJOR = Number(process.versions.node.split(".")[0]);
const IS_WINDOWS = process.platform === "win32";
const RUN_CSS_TESTS = NODE_MAJOR >= 18 && !IS_WINDOWS;

module.exports = {
testEnvironment: "node",
coveragePathIgnorePatterns: ["src/serialize-javascript.js"],
testPathIgnorePatterns: RUN_CSS_TESTS
? []
: ["/test/css-minify-option\\.test\\.js$"],
};
Loading
Loading