Search by

meekmedia / image-optimizer

manish-sharmaa

Private, client-side image compression widget for any PHP site. MozJPEG, WebP and OxiPNG via WebAssembly - images never leave the visitor's browser.

Package info

github.com/manish-sharmaa/image-optimizer

Language:JavaScript

pkg:composer/meekmedia/image-optimizer

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1.0 2026-09-01 07:07 UTC

This package is auto-updated.

Last update: 2026-09-01 07:09:27 UTC


README

Private, client-side image compression for any PHP site. Drop in a widget that compresses JPEG, PNG and WebP in the visitor's browser with the same WebAssembly codecs used by Google's Squoosh app (MozJPEG, libwebp, OxiPNG) - images never touch your server, so it works on the cheapest shared hosting and scales for free.

Built by Meek Media.

Why

  • Private: files never leave the browser. No uploads, no storage, no GDPR surface.
  • Real codecs: MozJPEG / WebP / OxiPNG via WASM - visibly better than canvas.toBlob.
  • Live: dragging the quality slider or switching format re-compresses already-added images in place, sizes updating in real time.
  • Server-proof: your PHP just prints markup and serves static files. No extensions, no binaries, no upload_max_filesize, no queue.
  • Graceful: if WASM can't load, it silently falls back to the browser's canvas encoder.

Install

Composer

composer require meekmedia/image-optimizer

No Composer? Download the release zip, unzip it anywhere PHP can read, and require '<path>/image-optimizer/autoload.php';.

Quick start

  1. Publish the static assets into your public web root:
php vendor/meekmedia/image-optimizer/bin/publish-assets.php public/assets/image-optimizer
  1. Render the widget:
<?php
use MeekMedia\ImageOptimizer\{Config, Optimizer};

$optimizer = new Optimizer(new Config(
    publicUrl: '/assets/image-optimizer',              // URL where you published the assets
    publicPath: __DIR__ . '/assets/image-optimizer',   // optional: enables mtime cache busting
));
?>
<html>
<head><?= $optimizer->headTags() ?></head>
<body>
  <?= $optimizer->render(['formats' => ['auto', 'webp', 'mozjpeg', 'oxipng'], 'resize' => true]) ?>
  <?= $optimizer->scriptTags() ?>
</body>
</html>

That's it. See examples/plain-php/ for a runnable page.

Upgrading

After updating the package (Composer or the release zip), re-run the publish step so the new static assets land in your public web root:

php vendor/meekmedia/image-optimizer/bin/publish-assets.php public/assets/image-optimizer

Asset URLs are version-busted (?v=...), so browsers and CDNs with long-lived cache headers pick up the republished files automatically - no manual cache purge needed.

Options (render config)

Key Default Meaning
formats ['webp','mozjpeg','oxipng'] Formats offered in the select. 'auto' keeps each image's own format.
defaultFormat 'webp' Pre-selected format.
quality 80 1-100. Ignored by OxiPNG (lossless).
resize false Show a max-dimension input (fit-within, never upscales).
maxFiles 20 Batch limit per drop.

Advanced (JS-only, via MeekImageOptimizer.mount(el, options)): strings to override every UI string, and onFileComplete / onBatchComplete / onError callbacks. A headless API is also exposed: MeekImageOptimizer.create({assetsBase}).then(o => o.compress(file, opts)).

Notes

  • v1 limitation: render() (and the widget it mounts) supports only one instance per page - rendering it more than once on the same page isn't supported yet.

Theming

The widget is styled entirely through CSS custom properties - set them on .mio-root:

.mio-root {
  --mio-accent: #32b49a;
  --mio-accent-contrast: #fff;
  --mio-bg: transparent;
  --mio-card-bg: #fff;
  --mio-text: #141414;
  --mio-muted: #6b7280;
  --mio-border: #e5e7eb;
  --mio-radius: 20px;
  --mio-font: inherit;
}

Dark mode: redefine the same variables under your dark scope (e.g. .dark .mio-root { ... }).

Server notes

  • Serve .wasm with the right MIME type (the widget copes either way, but streaming compilation is faster). Apache/.htaccess:
AddType application/wasm .wasm
  • All codecs are single-threaded WASM: no COOP/COEP headers are needed.
  • Images above 24 megapixels are rejected client-side (mobile Safari canvas limits).

Browser support

Evergreen Chrome, Edge, Firefox, Safari (incl. iOS). Older browsers get the canvas fallback automatically.

Attribution & license

Apache-2.0. Bundles WebAssembly codecs from jSquash, derived from Google's Squoosh (both Apache-2.0) - "Squoosh" is used for attribution only; this project is not affiliated with Google. ZIP support by fflate (MIT). See THIRD_PARTY_NOTICES.md.