npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@alberteinshutoin/lazy-image

v1.4.1

Published

Web image optimization engine for Node.js with Image Firewall-backed secure upload defaults and smaller JPEG outputs in canonical PNG → JPEG benchmarks, powered by Rust + mozjpeg

Readme

lazy-image 🦀

Build verified web-image artifacts in your Node.js upload or build pipeline. lazy-image combines policy-driven responsive output, metadata checks and a manifest, then commits the verified set to a local directory. Powered by Rust, it also provides a lazy API for individual image optimization.

npm version Node.js CI License: MIT

Node.js 22+ · prebuilt for macOS arm64/x64, Linux x64 GNU/musl and arm64 GNU, and Windows x64 · JPEG/PNG/WebP input · JPEG/PNG/WebP/AVIF output

日本語 · Documentation · API · Examples · Performance

Choose your workflow

| You need | Start with | |---|---| | A verified public image set from one local upload | compileImage() or CLI | | One optimized file or Buffer | Quick start and ImageEngine | | Browser/Edge upload preflight | Separate Wasm package | | Product fit and alternatives | Product direction · Competitor analysis |

You own upload admission, job execution, storage and delivery. The compiler's commit is a local filesystem operation; it does not upload to a CDN or object store.

Install

npm install @alberteinshutoin/lazy-image

Prebuilt native binaries are installed automatically on supported platforms.

Quick Start

import { ImageEngine } from '@alberteinshutoin/lazy-image';

const image = await ImageEngine.fromPathAsync('input.png');
const bytesWritten = await image
  .resize({ width: 800, fit: 'inside' })
  .toFile('output.jpg', 'jpeg', 80);

console.log(`Wrote ${bytesWritten} bytes`);

Use fromPathAsync() in servers so file setup does not block the Node.js event loop. CommonJS is also supported:

const { ImageEngine } = require('@alberteinshutoin/lazy-image');

Common tasks

Buffer to WebP

import { readFile } from 'node:fs/promises';
import { ImageEngine } from '@alberteinshutoin/lazy-image';

const input = await readFile('input.jpg');
const output = await ImageEngine.from(input)
  .resize({ width: 1200 })
  .toBuffer('webp', 80);

Sanitize an upload

const output = await ImageEngine.from(uploadBuffer)
  .sanitize({ policy: 'public-upload' })
  .resize({ width: 1600, height: 1600, fit: 'inside' })
  .toBuffer('jpeg', 85);

The public-upload policy enforces resource limits and strips EXIF, GPS, and XMP while preserving only validated ICC profiles.

For a complete, fail-closed artifact set, use the transactional compiler. It creates library-owned responsive filenames and manifest.json in private staging, then publishes the directory only after verification:

const { compileImage } = require('@alberteinshutoin/lazy-image');

const manifest = await compileImage({
  inputPath: '/srv/uploads/image.bin',
  outputDir: '/srv/public/images/v1',
  policy: { widths: [320, 640], formats: ['webp'], placeholder: true },
});

Existing output directories are rejected and full artifact bytes are never returned as Node.js buffers. The output parent must be trusted, without concurrent replacement, and staging must share its filesystem. See the compiler contract.

CLI artifact compilation

Create a policy JSON file, then compile one input into a new output directory:

{"widths":[320,640],"formats":["webp"],"placeholder":true}
npx @alberteinshutoin/lazy-image compile input.jpg \
  --out-dir public/images/v1 \
  --policy policy.json

On success, stdout contains only the generated manifest JSON. Diagnostics go to stderr; exit 0 means success, exit 2 means invalid CLI arguments or policy JSON, and exit 1 means compiler failure. Failed compilations do not publish the set; see failure handling for API cleanup diagnostics and CLI limitations.

Inspect without decoding

import { inspectFile } from '@alberteinshutoin/lazy-image';

const { width, height, format } = inspectFile('input.jpg');

Main API

ImageEngine.from(buffer)
await ImageEngine.fromPathAsync(path)

.resize({ width?, height?, fit? })
.crop(x, y, width, height)
.rotate(90 | 180 | 270)
.flipH() / .flipV() / .grayscale()
.sanitize({ policy })

await .toFile(path, format, quality?)
await .toBuffer(format, quality?)
await .encode({ format, quality?, preset?, metrics? })
await .toResponsiveSet({ widths, format, quality? })
await .toFilesResponsive('path-{width}.webp', { widths, format, quality? }, srcsetPattern?)
await .toPlaceholder({ size?, format?, quality? })

Operations are queued and evaluated once when an output method runs. Use clone() when producing multiple variants from one source. See the full API reference for batch processing, presets, metrics, streaming, metadata controls, responsive output helpers, and error codes.

When to use it

Choose lazy-image when you want policy-driven artifacts and a manifest in an existing upload/build job, or its file-oriented optimization API. Metadata stripping and resource limits are important defaults, not exclusive advantages. Use sharp for broader editing/format needs; consider an HTTP image server or managed image service when on-demand transformation and delivery are the main job. See the competitor analysis for the distinctions and performance evidence for scoped codec comparisons.

Safety and limits

  • Metadata is stripped by default. Use keepMetadata() only when needed.
  • File inputs up to 256 MB use Rust-owned memory; larger files may use mmap. Do not modify or delete an mmap-backed source while processing it.
  • Rotation supports 90°, 180°, and 270°.
  • 16-bit images are converted to 8-bit.
  • Animated GIF/APNG, drawing, and heavy filters are out of scope.

Details: metadata · file I/O · thread model · errors

Browser and Edge

Use the separate Wasm package for browser and V8-isolate upload preflight:

npm install @alberteinshutoin/lazy-image-wasm

See the Wasm package guide. Validate bundle size and latency in the target runtime before production use.

Development

npm install
npm run build
npm test

See contributor documentation for build requirements, contracts and verification.

License

MIT. Built with mozjpeg, libwebp, libavif, fast_image_resize, img-parts, and NAPI-RS.