node-minify turns a pile of compressors into one minify call
Light Node.js module that compress javascript, css and html files
At a glance
- What is it?
- node-minify is an MIT licensed Node.js library that compresses JavaScript, CSS, HTML, JSON and images by wrapping existing tools rather than reimplementing them. Version 11 split it into separate packages per compressor, dropped CommonJS support, and requires Node.js 22 or later with ESM only.
- Who is it for?
- Adopt node-minify if you want one minify call that can switch compressor per file type, or if you want to compare compressors on your own assets before committing to one. Skip it if you already have a working bundler pipeline, since minifying is a step most build tools do for you.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A facade over other minifiers, not a minifier
The project describes itself as a very light minifier Node.js module whose job is to compress JavaScript, CSS, HTML and image files. What it actually is, and this is the important thing to understand before you adopt it, is a uniform interface over a catalogue of other tools. The JavaScript side covers esbuild, Google Closure Compiler, oxc, swc, terser and uglify-js. The CSS side covers clean-css, cssnano, CSSO, esbuild and lightningcss. HTML is handled by minify-html, described as Rust-based and recommended, and html-minifier. JSON is handled by jsonminify, marked legacy. Images go through sharp for WebP and AVIF conversion, svgo for SVG optimisation and imagemin for PNG, JPEG and GIF compression. There is also a no-compress option and a command line interface. So the value proposition is not that node-minify minifies better than terser. It is that you can hand it a file and let it pick the right tool, and swap tools without touching your code.
Installing the core and then the compressors you want
The core package is installed first, and the README gives four package managers.
npm install @node-minify/core
# Or Yarn
yarn add @node-minify/core
# Or pnpm
pnpm add @node-minify/core
# Or Bun
bun add @node-minify/coreThe compressors are separate packages, so you only install the ones you need, and the README marks the recommended ones. For JavaScript that is terser, described as modern, fast and well-maintained, esbuild, described as extremely fast and also handling CSS, swc and oxc, both Rust-based, with uglify-js and google-closure-compiler listed as supported.
npm install @node-minify/terser # Recommended - modern, fast, well-maintained
npm install @node-minify/esbuild # Recommended - extremely fast, also handles CSSFor CSS the recommended set is lightningcss, Rust-based and fastest, cssnano, PostCSS-based and customisable, and esbuild, while clean-css and csso are marked supported. For HTML and other types, minify-html is recommended as Rust-based and fastest, html-minifier is supported, and jsonminify is marked legacy. For images, sharp is recommended for WebP and AVIF conversion with high performance, svgo for SVG optimisation and imagemin for PNG, JPEG and GIF compression.
The minify call, and how the compressor is selected
The API takes a compressor and either an input path or literal content.
import { minify } from '@node-minify/core';
import { gcc } from '@node-minify/google-closure-compiler';
import { terser } from '@node-minify/terser';
// Using Google Closure Compiler
const result = await minify({
compressor: gcc,
input: 'foo.js',
output: 'bar.js'
});The same call handles a glob, which is how you bundle a whole directory of sources into one output file, and it works with a promise chain if you prefer not to use await.
const min = await minify({
compressor: terser,
input: 'src/**/*.js',
output: 'dist/bundle.js'
});Because the compressor is a value passed in rather than a flag on the command, choosing a different tool is a one-line change in your build script. That is the whole design in one parameter.
Minifying a string in memory instead of a file
The other mode takes content directly, which is what you want when the input is a string you already have, for example HTML served from a template or a string fetched at build time.
import { minify } from '@node-minify/core';
import { htmlMinifier } from '@node-minify/html-minifier';
const html = `
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
</html>`;
const min = await minify({
compressor: htmlMinifier,
content: html
});
console.log(min);The switch between the two modes is whether you pass input or content, and the same compressor object works with either. The repository carries a fuller example in examples/server.js, and the documentation site at node-minify.2clics.net holds the rest, including the options reference and the compressor comparison pages.
The v11 break: ESM only, Node 22, and split packages
The requirements section is short and strict. Node.js 22 or higher, and the module system is ESM only, meaning type module in package.json. That is the single most consequential change for existing users, since a CommonJS project cannot require this any more. The second change is the package layout. What used to be one package is now a core package plus one package per compressor, which is why the installation instructions list each compressor separately and why the README links a v11 migration guide. The guide comes with a diagnostic you can run against your own project, using npx with the @node-minify/cli package and the doctor subcommand, which scans the project for the changes the upgrade needs.
The releases show the pace of the change: v11.0.0 on 2026-09-02, v10.5.0 on 2026-03-08 and v10.4.0 on 2026-01-22, with the last push to the repository on 2026-10-20. The repository itself is a monorepo on Bun, with a packages directory, a docs package built separately, and the root package marked private with a description of it as the monorepo for node-minify.
Command line, benchmarks and the project layout
Two things beyond the library API are worth knowing about. There is a command line interface documented separately, and there is a benchmark page for comparing compressor performance, which is the honest way to answer the question of which tool to use on your assets rather than guessing from the recommendations in the README. The repository layout explains the shape of the project. There is a packages directory holding the individual published packages, a docs directory with its own build step, tests, an examples directory with a server example and a public folder, scripts, and a static directory. The tooling around it is modern rather than minimal: Biome for linting and formatting, Vitest with coverage, tsdown for the build, changesets for versioning and releases, and Renovate for dependency updates. The CI script chains a build, an export check, a lint, a typecheck and a coverage run, which is a reasonable quality bar for a package that other people's build steps depend on.
Where node-minify is the wrong choice
Three limits. The first is that it duplicates what your build tool already does. Any modern bundler can minify JavaScript and CSS as part of the build, and the esbuild path here would mean running esbuild twice unless you disable the bundler's own minification. The library earns its place when you are minifying assets outside a bundler, when you want per-file-type compressor choice, or when you are comparing compressors on real files. The second is the dependency surface. Because every compressor is a separate npm package, a project that minifies JavaScript, CSS, HTML and images pulls in terser or esbuild, lightningcss or cssnano, minify-html and sharp or imagemin, and sharp in particular is a large binary dependency with native builds. The README's own framing of itself as a very light module sits awkwardly beside that list. The third is that the newest version is a breaking one. Version 11 requires Node 22 and ESM only, so adopting it means either modernising the host project or staying on the 10.x line, and the 10.x line is no longer receiving the same attention. There is also no mention in the README of caching, incremental builds or watching, so a build that minifies the same assets on every run will pay the compressor cost every time.
Editorial conclusion
Adopt node-minify if you want one minify call that can switch compressor per file type, or if you want to compare compressors on your own assets before committing to one. Skip it if you already have a working bundler pipeline, since minifying is a step most build tools do for you. Before you upgrade from version 10, read the v11 migration guide and run the doctor command, because the package layout changed and CommonJS support is gone.
Frequently asked questions
What does node-minify do?
It compresses JavaScript, CSS, HTML, JSON and image files through one minify call. It does not implement the compressors itself: JavaScript is handled by esbuild, Google Closure Compiler, oxc, swc, terser or uglify-js, CSS by clean-css, cssnano, CSSO, esbuild or lightningcss, HTML by minify-html or html-minifier, JSON by jsonminify, and images by sharp, svgo and imagemin.
How do I install node-minify and a compressor?
Install the core package with `npm install @node-minify/core`, or the equivalent yarn, pnpm or bun command, then install only the compressors you want, for example `npm install @node-minify/terser` for JavaScript. The README marks terser, esbuild, swc and oxc as recommended for JavaScript, lightningcss, cssnano and esbuild for CSS, minify-html for HTML, and sharp and svgo for images.
Can node-minify minify a string instead of a file?
Yes. Pass content rather than input, for example `minify({ compressor: htmlMinifier, content: html })`, and the compressed result comes back as the return value. The same compressor object works with either the input path or the content form.
What changed in node-minify version 11?
The requirements are Node.js 22 or higher and ESM only, so CommonJS projects can no longer require it, and the release is split into a core package plus one package per compressor. The README links a v11 migration guide and a diagnostic command, `npx --package=@node-minify/cli -- node-minify doctor`, to scan an existing project.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/srod-node-minify)Was this useful?