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

v0.14.0

Published

Web image optimization engine for Node.js - smaller files than sharp, powered by Rust + mozjpeg

Readme

lazy-image 🦀

Web image optimization engine for Node.js. Rust core, smaller outputs than sharp.

lazy-image reduces image file sizes by 20-30% compared to sharp in its target web-delivery scenarios, trading encoding speed for smaller outputs. Ideal for CDN-heavy workloads where bandwidth costs matter more than CPU costs.

  • Not a drop-in replacement for sharp — use sharp if you need its full API or maximum throughput.
  • Security-first: Metadata stripped by default; keepMetadata() to preserve. Zero-copy path: fromPath()/processBatch()toFile().
  • Japanese: README.ja.md. mmap: Do not modify/delete source files while processing; use a copy or from(Buffer) for mutable inputs.
  • Lazy contract: docs/LAZY_SEMANTICS.md explains what is deferred vs eager.
  • Metadata matrix: docs/METADATA_SUPPORT.md.
  • Philosophy and non-goals: docs/PROJECT_PHILOSOPHY.md.

npm version npm downloads Node.js CI codecov License: MIT Rust


Quick Start (5 lines)

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

const bytesWritten = await ImageEngine.fromPath('input.png')
  .resize(800)
  .toFile('output.jpg', 'jpeg', 80);

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

Architecture Overview

src/                        # Rust core
├── engine/
│   ├── api.rs              # ImageEngine public API + NAPI bindings
│   ├── pipeline.rs         # Operation queue, validation, optimization
│   ├── resize.rs           # Dimension calc, fast_image_resize dispatch
│   ├── tasks.rs            # NAPI async tasks (encode, batch, target-bytes)
│   ├── encoder.rs          # JPEG/PNG/WebP/AVIF encoding + ICC/EXIF embedding
│   ├── decoder.rs          # Format detection + decoding
│   ├── firewall.rs         # Input sanitization policies
│   ├── memory.rs           # Cgroup detection, concurrency estimation
│   └── io.rs               # File I/O, mmap, ICC/EXIF extraction
├── ops.rs                  # Operation enum, presets, output formats
├── error.rs                # 4-tier error taxonomy (E1xx–E9xx)
└── codecs/avif_safe.rs     # Safe libavif FFI wrappers

lib/helpers.js              # Encoding profiles, target-bytes binary search
streaming/pipeline.js       # Disk-backed bounded-memory streaming

Key design decisions: lazy execution (ops queue until output), zero-copy file I/O via mmap, memory-bounded concurrency via weighted semaphore, panic guards on all codec entry points. See docs/ARCHITECTURE.md for details.


Choose lazy-image if / Choose sharp if

| Choose lazy-image if | Choose sharp if | |---|---| | You pay for bandwidth (CDN, S3, CloudFront) | You need maximum encoding throughput | | You run in serverless / memory-constrained envs | You need a broad image editing API | | You want AVIF with good defaults | You need drop-in API compatibility | | You want smaller outputs over faster encodes | You need GIF, SVG, or TIFF support |

Key differentiators:

  1. File size optimization — mozjpeg + libwebp + ravif produce 20-30% smaller outputs than sharp's defaults
  2. Memory efficiency — zero-copy mmap architecture; no pixel data copied to the JS heap
  3. Security-first — GPS auto-strip, Image Firewall, Rust memory safety
  4. AVIF excellence — ravif encoder with quality-optimized defaults

What lazy-image does NOT compete on: raw encoding speed (sharp/libvips is faster), feature breadth (no drawing, compositing, or GIF), API compatibility with sharp.

Project philosophy: optimize for smaller web outputs, bounded memory, and safe defaults first. Any speed claims must be codec- and workload-specific, not a blanket "faster than sharp" promise.

Benchmarks and details: docs/PERFORMANCE.md. Full compatibility matrix: docs/COMPATIBILITY.md.


Recommended Paths

Start with one of these workflows:

  • Web delivery optimization: fromPath() -> resize()/crop() -> toFile() for the lowest heap usage and the clearest operational path
  • Upload sanitization: fromPath() -> sanitize({ policy: 'strict' }) -> toFile()/toBuffer() for untrusted user uploads
  • Build-time / batch generation: processBatch() or clone() for static sites, media pipelines, and multi-output generation
  • Final optimization after editing: use sharp/ImageMagick for compositing, filters, or animation, then pass the result through lazy-image for final JPEG/WebP/AVIF optimization

Scenario guide: docs/ADOPTION_GUIDE.md.


Cost Savings Example (ROI)

Assume:

  • average image size before optimization: 1.0 MB
  • average reduction with lazy-image: 25%
  • CDN transfer rate: $0.085/GB (example: CloudFront pay-as-you-go, US/EU next 9TB tier)

| Scenario | Transfer with sharp | Transfer with lazy-image | Monthly savings | |---|---:|---:|---:| | 1M image deliveries / month | 976.6 GB | 732.4 GB | $20.75 | | 10M image deliveries / month | 9.54 TB | 7.15 TB | $207.52 | | 100M image deliveries / month | 95.37 TB | 71.53 TB | $2,075.20 |

Break-even intuition:

  • Encoding overhead is paid once per generated image
  • Bandwidth savings are realized every time the image is delivered
  • If each generated image is viewed multiple times, lazy-image generally wins quickly

Use the interactive calculator:


Installation

npm install @alberteinshutoin/lazy-image

Platform-specific binaries (~6–9 MB per platform) are installed automatically. Build from source: npm run build. See docs/PERFORMANCE.md for package size comparison with sharp.


Basic Usage

Resize and save (recommended: file-to-file)

await ImageEngine.fromPath('photo.jpg')
  .resize({ width: 800, fit: 'inside' }) // positional args also supported
  .toFile('thumb.jpg', 'jpeg', 85);

Format conversion (e.g. PNG → WebP/AVIF)

const buffer = await ImageEngine.fromPath('input.png')
  .resize({ width: 600 })
  .toBuffer('webp', 80);

Metadata without decoding

const { inspectFile } = require('@alberteinshutoin/lazy-image');
const meta = inspectFile('input.jpg'); // { width, height, format }

lazy-image defers full pixel decode, transforms, and encoding until toBuffer() / toFile(). Constructors still do source setup and metadata extraction; see docs/LAZY_SEMANTICS.md.

More: batch processing, presets, metrics, streaming — docs/API.md.


Documentation

| Topic | Link | |-------|------| | Examples | examples/ | | TypeScript guide | docs/TYPESCRIPT.md | | Full API reference | docs/API.md | | Migration from sharp | docs/MIGRATION_FROM_SHARP.md | | Performance & when to use | docs/PERFORMANCE.md | | Architecture & security | docs/ARCHITECTURE.md | | Troubleshooting | docs/TROUBLESHOOTING.md | | Security policy & reporting | SECURITY.md | | Roadmap & scope | docs/ROADMAP.md | | Adoption guide / recommended workflows | docs/ADOPTION_GUIDE.md | | Metadata support matrix | docs/METADATA_SUPPORT.md | | ROI calculator methodology | docs/ROI_CALCULATOR.md | | Version history | docs/VERSION_HISTORY.md | | Specification (spec/) | spec/pipeline.md, spec/resize.md, spec/errors.md, spec/limits.md, spec/quality.md, spec/metadata.md | | Error codes | docs/ERROR_CODES.md | | Benchmarks (raw data) | docs/TRUE_BENCHMARKS.md | | Binary size comparison (AVIF on/off) | docs/BINARY_SIZE.md | | Benchmark snapshots log | docs/BENCHMARK_RESULTS.md | | Benchmark operations | docs/BENCHMARK_OPERATIONS.md |


Features (summary)

Smaller JPEG (mozjpeg) · Smaller WebP (libwebp) · AVIF (ravif) · ICC profiles · EXIF auto-orient · Zero-copy file I/O · Disk-backed bounded-memory pipeline (createStreamingPipeline(), not true chunked transform streaming) · Image Firewall · GPS auto-strip · Fluent API · Rust core (NAPI-RS) · Cross-platform (macOS, Windows, Linux). Design choices and limits: docs/ROADMAP.md and docs/ARCHITECTURE.md.


Development

npm install && npm run build
npm test

See CONTRIBUTING.md for workflow, test commands, and contribution guidelines. Benchmark testing: lazy-image-test Docker environment. Fuzzing: FUZZING.md.


License

MIT


Credits

mozjpeg · libwebp · ravif · fast_image_resize · img-parts · napi-rs


Ship it. 🚀