A Vite plugin that makes your build's images smaller, automatically. No config required to get started, no changes to your source files, and no separate compression step to remember before every commit.
When Vite builds your site, it copies your images into the dist folder as
they are. This plugin re-compresses those copies on the way out using
sharp, so the images you actually ship end
up smaller than the ones you started with.
A few things this plugin is careful about, so it's safe to just turn on:
- Your original files are never touched. Only the copies written to
dist/get re-encoded. Nothing in your project or Git history changes. - Only images that actually ship get processed. If an image never makes it into your build output, this plugin never looks at it.
- You never end up with a bigger file. If re-compressing an image
wouldn't save meaningful space, the original is kept instead (see
minSavingsbelow).
Add the plugin, build your site the way you normally would, and your images come out smaller. That's the whole idea.
npm install --save-dev @binarynoir/vite-plugin-optimize-images// vite.config.ts
import { defineConfig } from "vite";
import { optimizeImagesPlugin } from "@binarynoir/vite-plugin-optimize-images";
export default defineConfig({
plugins: [optimizeImagesPlugin()],
});That's it — .png, .jpg/.jpeg, and .webp assets in your build output
get re-encoded automatically. Run a build with VITE_OPTIMIZE_VERBOSE-style
visibility by passing verbose: true (see below) to see what was optimized
and by how much.
| Option | Default | Description |
|---|---|---|
minSize |
10240 |
Minimum source size (bytes) before an image is considered for optimization (10 KiB). |
minSavings |
1024 |
Minimum bytes an optimization must save before it's applied (1 KiB). |
png |
— | sharp PNG encode options override. |
jpeg |
— | sharp JPEG encode options override. |
webp |
— | sharp WebP encode options override. |
verbose |
false |
Log progress and per-file savings to the console. |
Defaults, before any override:
{
png: { quality: 80, compressionLevel: 9, adaptiveFiltering: true },
jpeg: { quality: 85, progressive: true, mozjpeg: true },
webp: { quality: 85 },
}optimizeImagesPlugin({
minSize: 5 * 1024,
minSavings: 512,
jpeg: { quality: 75 },
verbose: true,
});Those are great, more general options if you want format conversion, resizing, or a wider codec set. This plugin is intentionally small: it re-encodes the three formats sharp handles fastest, only ever operates on what's already in the output bundle (so it composes cleanly with any other asset pipeline you have), and never risks producing a larger file than it started with.
Releases are tag-triggered. To ship a new version, from a clean main that's
in sync with origin/main:
npm run release:patch # or release:minor / release:majorThis runs typecheck/lint/test/build locally, then npm version <bump>
(bumps package.json, commits, and creates a matching vX.Y.Z tag) and
git push --follow-tags. Pushing that tag triggers
.github/workflows/release.yml, which
re-runs the checks, publishes to npm (with
provenance), and
creates a GitHub release with auto-generated notes.
For a prerelease or an explicit version, use npm run release -- <arg>
(e.g. npm run release -- 1.2.3 or npm run release -- prerelease) — see
npm version for the
full list of accepted values.
This requires an NPM_TOKEN repository secret (an npm
automation token
with publish access) — set it under Settings → Secrets and variables →
Actions. First time publishing this package? See PUBLISHING.md.
If you encounter any issues or have questions, please open an issue on GitHub.
John Smith III
Thanks to all contributors and users for their support and feedback.