# tdewolff/minify: Go Minifiers for HTML, CSS, JS, JSON, SVG and XML

> A Go library and CLI that minifies web formats through real parsers rather than regexes, with embedded resources handled by mimetype. Fast, MIT licensed, and maintained, but the documentation is thin on rollback and the SVG minifier is flagged as slow.

**tdewolff/minify** — Go minifiers for web formats

- Repository: https://github.com/tdewolff/minify
- Website: https://go.tacodewolff.nl/minify
- Stars: 4,142 · Forks: 243
- Language: Go
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/tdewolff-minify

## What tdewolff/minify removes, and who needs that

Minification strips bytes from a file without changing its output, which shrinks the payload and speeds up transmission. That is the whole premise, and it is a narrow one. The library targets people who already have a build or serving step they control: a Go web service that wants to compress responses on the way out, or a release pipeline that wants smaller static assets. It is not a design tool and it does not transform code semantics.

The README is blunt about why it exists. Many minifiers in other languages are, in its words, "merely using several regular expressions to trim whitespace and comments", and it cites the Coding Horror essay on regex parsing of HTML to argue that this approach is ill-advised. The project's answer is a set of real parsers, built on the sibling tdewolff/parse module, for HTML5, CSS3, JS, JSON, SVG and XML. If your current minifier occasionally mangles a template or a string literal, that difference in approach is the reason to look here.

The scope is deliberately broader than a single format. Because the core associates mimetypes with minification functions, a CSS block or a script tag inside an HTML document can be minified as part of the same pass. That is the feature that distinguishes it from a one-format tool, and it is also where the configuration surface starts to matter.

## Mimetype dispatch and the custom minifier interface

The architecture is a registry, not a pipeline. A Minify value holds a mapping from mimetype (or a pattern) to a minification function, and the HTML minifier consults that mapping when it encounters embedded resources. You register the subpackages you want, and the dispatch happens by content type.

That design has two consequences worth understanding before you build on it. First, you can add your own implementation for a type the project does not cover, and it will be invoked by the same mechanism. Second, you can redirect a mimetype to an external command instead of handling it in process. The README names ClosureCompiler, UglifyJS and esbuild as examples of external minifiers you can wire in this way, and the examples section documents each. So the library is a dispatch layer as much as it is a set of minifiers.

The trade-off is that correctness now depends on mimetype detection being right. If a server hands your HTML minifier a content type it does not recognise for an embedded block, that block passes through untouched rather than being minified. Nothing breaks; you just silently get fewer bytes saved than you expected. That is a failure mode you will not see in a test suite unless you assert on output size.

## Installing the library and minifying a string

The README requires Git and Go 1.18 or higher for the library, and the repository's go.mod declares go 1.25.0, so in practice you should be on a recent toolchain. The installation sequence creates a module and pulls the dependency:

```bash
mkdir Project
cd Project
go mod init
go get -u github.com/tdewolff/minify/v2
```

Then add the imports for the minifiers you actually use. Importing all six pulls in parsers you may not need:

```go
import (
	"github.com/tdewolff/minify/v2"
	"github.com/tdewolff/minify/v2/css"
	"github.com/tdewolff/minify/v2/html"
	"github.com/tdewolff/minify/v2/js"
	"github.com/tdewolff/minify/v2/json"
	"github.com/tdewolff/minify/v2/svg"
	"github.com/tdewolff/minify/v2/xml"
)
```

The README documents several entry points for a first real use: New, From reader, From bytes, From string, To reader, To writer, Middleware, Custom minifier and Mediatypes. If you are serving HTTP, the Middleware option is the one to read first, because it wraps a handler rather than requiring you to buffer and rewrite responses yourself. The README does not document rollback for a minified response, so if you need the original bytes to remain retrievable, that is on you to keep.

## The CLI, Docker image and language bindings

If you do not want a Go dependency in your application, the project ships a command line tool. Prebuilt binaries for various platforms are on the releases page, and the cmd/minify directory holds the installation instructions. On Windows, scoop installs it:

```bash
scoop install main/minify
```

There is also an official image, and the README gives this invocation:

```bash
docker run -it tdewolff/minify --help
```

The repository's Dockerfile builds the binary in a golang:1.25-alpine stage with make install, then copies it into an alpine:3 final image with an entrypoint script. That is a small image, and it means the CLI is usable from a container without a Go toolchain on the host.

For teams not writing Go, the README points to bindings: Python via pip install tdewolff-minify, JavaScript via npm i @tdewolff/minify, and a .NET port, NMinify, credited to Jonas Kamsker and installable with dotnet add package NMinify. The bindings directory in the repository is where those live. A binding is a different maintenance surface from the library, so pin the version you test against.

## Where tdewolff/minify is the wrong tool

Source maps are the clearest gap. The roadmap lists "Generation of source maps" as uncertain, with the stated reason that it might slow down the parsers too much if it cannot run separately. If your workflow depends on mapping minified positions back to original source, this project does not currently give you that, and the roadmap does not promise it will.

The SVG minifier is the second. The roadmap carries an unchecked item reading "Speed-up SVG minifier, it is very slow". That is the maintainer's own assessment, and it sits awkwardly next to the project's broader performance positioning, which cites an external benchmark repository where the library is described as one of the fastest JS minifiers. Fast JS does not imply fast SVG. If SVG is a large part of your asset pipeline, measure it on your own files before you assume the general reputation carries over.

The third limitation is API stability. The README says there is no guarantee of absolute stability, that there has been one API change after v1 when options support was added, and that there are no plans for further changes. That is a reasonable position, but it is not a compatibility promise. Treat upgrades as something to test rather than assume.

## How it differs from Closure Compiler and esbuild

The obvious alternative for JavaScript is Google Closure Compiler, and the difference is not just speed. Closure Compiler performs advanced optimisations: it can rename properties, inline functions and eliminate dead code across a whole program, and it requires you to annotate your code for the aggressive modes to be safe. tdewolff/minify does not do that. It shortens variables and omits semicolons where it can, and the roadmap marks that work as done, but it stays within the semantics of the input. If you need whole-program optimisation, Closure Compiler is the tool, and the README treats it as a companion rather than a rival by documenting how to call it as an external minifier.

esbuild is the other comparison point, and it is a bundler first. It resolves imports, produces a single output file, and minifies as part of that. tdewolff/minify does not bundle. The roadmap has an unchecked item for a cmd to pack webfiles, merging CSS and JS, inlining small external files, minifying and gzipping, explicitly compared to webpack, and it is not built. So if you need bundling, esbuild covers it and this library does not. If you already have a bundler and want the smallest possible minification step for HTML, CSS, JSON, SVG or XML, the scope here is wider than esbuild's.

## Licence, releases and what maintenance costs you

The project is MIT licensed, and the repository's Makefile copies LICENSE into every release archive, so the terms travel with the binaries. MIT is permissive: you can use the library in closed-source products, and the obligation is essentially attribution and including the licence text. That is a description of the licence, not legal advice, and if your organisation has a policy on third-party notices you should route it through whoever owns that policy.

Maintenance looks current. The last push was on 2026-09-20, three days before this writing, and the most recent release listed is v2.24.17 on 2026-08-11, following v2.24.16 and v2.24.15 earlier in August. The version cadence is frequent and patch-level, which for a minifier usually means parser fixes and edge cases. The README also notes that SiteGround has sponsored the project for many years and that the maintainer is actively looking for donations or sponsorships, which is worth knowing if you are betting a build pipeline on it: the funding model is sponsorship, not a company.

Upgrade cost is mostly the dependency graph. The module requires github.com/tdewolff/parse/v2 for the parsers, plus argp for CLI argument handling and test for the test helpers, with fsnotify and atime pulled in for the CLI's file watching. A patch bump is unlikely to disturb your code, but the README's stance on API stability means you should read the release notes rather than assume.

## Conclusion

Adopt tdewolff/minify if you serve web assets from a Go service or build pipeline and want parsing-based minification in one dependency, with embedded CSS and JS handled by mimetype. Do not adopt it if you need source maps, since the roadmap lists them as uncertain, or if you expect the SVG minifier to be fast, because the roadmap says it is slow. Before committing, check the cmd/minify README for the CLI flags your build step needs and confirm your Go toolchain satisfies the go.mod requirement.

## FAQ

### What does tdewolff/minify do?

It is a minifier package written in Go that provides HTML5, CSS3, JS, JSON, SVG and XML minifiers plus an interface for implementing others. Minification removes bytes such as whitespace without changing the output, shrinking files and speeding up transmission.

### How do I install tdewolff/minify?

For the library, the README says to have Git and Go 1.18 or higher, create a module, then run go get -u github.com/tdewolff/minify/v2. For the CLI there are prebuilt binaries on the releases page, a scoop package on Windows, and a Docker image at tdewolff/minify.

### How do I minify JSON with tdewolff/minify?

The project includes a json subpackage, imported as github.com/tdewolff/minify/v2/json, and the README lists JSON among the supported formats alongside HTML, CSS, JS, SVG and XML. The usage section documents entry points such as From reader, From bytes and From string for feeding input to the minifier.

## Sources

- [License: MIT](https://github.com/tdewolff/minify/blob/master/LICENSE)
- [Project website](https://go.tacodewolff.nl/minify)
- [README](https://github.com/tdewolff/minify/blob/master/README.md)
- [Releases](https://github.com/tdewolff/minify/releases)
- [tdewolff/minify on GitHub](https://github.com/tdewolff/minify)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/tdewolff-minify
