Converting images to WebP is one of the cheapest ways to cut page weight — WebP is typically 25–35% smaller than an equivalent JPEG or PNG at matched quality. Doing it one file at a time in an online converter doesn’t scale. This guide converts a whole folder of .jpg and .png images to .webp in a single command, locally, with no upload and no account.
Everything below runs against @assetopt/cli (open source, MIT). The numbers at the end come from the downloadable sample pack — not hand-picked benchmarks.
Install
npm install -g @assetopt/cli
Or run it without installing:
npx @assetopt/cli --help
The one-command version
Point assetopt at a folder and it recurses into it. But by default the CLI recompresses images in their original format — to turn JPG and PNG into WebP you tell it so once, in a config file.
Create a .assetoptrc in your project that routes both source formats to WebP:
{
"images": {
"formatMatrix": { "jpeg": "webp", "png": "webp" },
"quality": { "webp": 82 }
},
"output": { "dir": "./optimized" }
}
Then convert the folder:
assetopt optimize ./images
Every .jpg and .png under ./images is written as .webp into ./optimized, mirroring the source tree. Your originals are left untouched.
Want every image type (including existing WebP/AVIF) normalized to WebP instead of a per-format rule? Use
{ "images": { "outputFormat": "webp" } }. See the config reference for the difference betweenoutputFormatandformatMatrix.
Preview the savings first
Before writing anything, run a dry run. analyze reports the exact before/after sizes without touching your disk:
assetopt analyze ./images
You’ll get a per-file table and a total. When the numbers look right, swap analyze for optimize.
Control the quality
WebP quality is a 1–100 dial (default 82). Lower means smaller files and more visible artifacts:
{ "images": { "formatMatrix": { "jpeg": "webp", "png": "webp" }, "quality": { "webp": 75 } } }
Re-run assetopt analyze ./images after each change — the incremental cache means only the files you changed are re-encoded, so tuning is fast.
Keep your originals separate
The output always goes to output.dir (default ./optimized), never over your source files. To send the WebP files somewhere specific for one run, override it without editing the config:
assetopt optimize ./images -o ./public/img
Real numbers
Running the config above on the sample pack (a web-perf-style routing of JPG/PNG → WebP):
| Source | Before | After (WebP) | Saved |
|---|---|---|---|
| Large PNG export (opaque photo) | 5.42 MB | 552 KB | −89.8% |
| JPEG photo | 1.74 MB | 1.44 MB | −17.4% |
PNG loses the most, because a photo saved as PNG is hugely oversized to begin with — WebP is the right container for it. A photo already saved as JPEG is closer to optimal, so the win is smaller but still real. You can reproduce these exact figures by downloading the pack and running the commands above.
When WebP isn’t the best target
For transparent PNGs (logos, icons), AVIF often keeps the alpha channel at a smaller size than WebP. assetopt can route by content — opaque → WebP, transparent → AVIF — automatically. That’s what the web-perf preset does; see Smart format conversion and the companion guide, Convert images to AVIF in bulk.
Next steps
- CLI reference — every command, flag, and exit code
- Configuration reference — all
.assetoptrcfields - Optimize images before deploying — wire this into your build