“Compress without losing quality” needs one honest caveat up front: all lossy image codecs (JPEG, WebP, AVIF) discard some data by design. What you can do is compress so the loss is not visible — recompress at a high quality setting and keep the original format, so you gain smaller files without a format switch or a visible drop. This guide does exactly that from the command line, locally.
Everything runs against @assetopt/cli (open source, MIT).
Why recompression still helps
Most images shipped by design tools and CMSes are exported well above the quality needed for the web, often with embedded metadata. Re-encoding them at a sane quality floor — in the same format — routinely trims a meaningful chunk with no perceptible change. If you’re willing to switch formats, WebP and AVIF save more; this guide is for when you need the format and name to stay put.
Install
npm install -g @assetopt/cli
The high-fidelity preset
assetopt ships a quality preset built for exactly this: every format is kept (no lossy format switch), re-encoded at a high quality floor (jpeg/png/webp: 95, avif: 90), with metadata preserved.
{ "preset": "quality" }
That’s the whole config. Then:
assetopt optimize ./images
Or tune quality by hand
Prefer explicit control? Set per-format quality yourself. Higher = closer to the original, larger files:
{
"images": {
"quality": { "jpeg": 90, "png": 90, "webp": 90 },
"stripMetadata": false
},
"output": { "dir": "./optimized" }
}
outputFormatis left at its default"keep", so a.jpgstays a.jpg.stripMetadata: falsekeeps EXIF/ICC data — important for stock photography where attribution or color profiles live in metadata. Set it totruewhen you don’t need them, for a bit more savings.
See the config reference for every field and its default.
Measure before you commit
The honest way to answer “did I lose quality?” is to look at both the numbers and the pixels. Start with a dry run:
assetopt analyze ./images
analyze reports the exact before/after size per file without writing anything. Then run optimize and spot-check a few outputs against the originals at 100% zoom. If a file looks soft, raise its format’s quality and re-run — the incremental cache only re-encodes what changed, so iterating is quick.
Finding your quality floor
There’s no universal “safe” number — it depends on the content (flat UI screenshots tolerate lower quality than skin tones or gradients). A practical loop:
- Start at
qualitypreset defaults (95 / 90). - Run
analyze, thenoptimize. - Compare a handful of outputs to the originals.
- Lower the number a few points and repeat until you just start to see a difference — then step back up.
Next steps
- Configuration reference → quality — per-format defaults and ranges
- Convert JPG & PNG to WebP in bulk — bigger savings if you can switch formats
- Optimize images before deploying — apply this in your build