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

@fe-fast/rusty-pic

v0.3.2

Published

🚀 高性能图片压缩工具,基于 Rust + WebAssembly 构建

Readme

Rusty-Pic

High-performance image optimization toolkit for the web. Rusty-Pic integrates seamlessly with Vite and Webpack, compresses images at build time with content-hashed outputs and auto-updated references, and supports optional cross-format transcode (e.g. PNG → WebP/AVIF).

Rusty-Pic 是一款高性能图片优化工具,深度集成 Vite 与 Webpack。它在构建阶段直接替换打包资产的字节,自动生成带内容哈希的产物并重写所有引用,可选开启跨格式转码(例如 PNG → WebP/AVIF)。


✨ Features | 功能特性

  • Build-pipeline native integration (Vite + Webpack): auto content hash + auto reference rewrite

  • Optional cross-format transcode: PNG/JPEG → WebP/AVIF, safe rename & reference updates

  • Real compression in Node builds (sharp), WASM path for browsers (with Canvas fallback)

  • Cache-aware and size-aware: only replace when smaller; cache to avoid repeated work

  • Simple DX: one plugin, minimal config; integration tests provided

  • 原生构建管线集成(Vite + Webpack):自动内容哈希与引用重写

  • 跨格式转码可选:PNG/JPEG → WebP/AVIF,安全改名与全量引用替换

  • Node 构建期真实压缩(sharp),浏览器端支持 WASM(并带 Canvas 兜底)

  • 感知缓存与体积:仅在更小时替换,缓存避免重复压缩

  • 开发者体验友好:一套插件,最小配置;提供可运行的集成测试


📦 Install | 安装

# npm
npm install @fe-fast/rusty-pic
# pnpm
pnpm add @fe-fast/rusty-pic
# yarn
yarn add @fe-fast/rusty-pic

⚙️ Vite Usage | Vite 使用

Default behavior: format='auto', transcode=false → keep original extensions (png stays png) and compress; references are auto-rewritten to hashed outputs.

默认行为:format='auto' 且 transcode=false → 保持原扩展名,仅同格式压缩;引用会自动重写到带哈希的产物。

Enable WebP transcode:

import { defineConfig } from 'vite';
import { rustyPic } from '@fe-fast/rusty-pic/vite';

export default defineConfig({
  plugins: [
    rustyPic({
      format: 'webp',      // target format
      transcode: true,     // allow cross-format rename
      quality: 80,         // 1-100
      // optional
      resize: { maxWidth: 1920, maxHeight: 1080, fit: 'inside' },
      cache: { enabled: true },
      dev: { enabled: false },
      build: { enabled: true },
      verbose: true
    })
  ]
});

Enable AVIF transcode:

rustyPic({ format: 'avif', transcode: true, quality: 70 })

🔧 Webpack Usage | Webpack 使用

Add the plugin and ensure images are treated as assets:

import RustyPicWebpackPlugin from '@fe-fast/rusty-pic/webpack';

export default {
  mode: 'production',
  module: {
    rules: [
      { test: /\.(png|jpe?g|webp|avif)$/i, type: 'asset/resource' }
    ]
  },
  output: {
    assetModuleFilename: 'assets/[name].[contenthash:8][ext]'
  },
  plugins: [
    new RustyPicWebpackPlugin({
      // default keeps original ext (no transcode)
      // set webp/avif to transcode and auto-rewrite references
      format: 'webp',
      quality: 80,
      verbose: true
    })
  ]
};

Notes | 说明:

  • Webpack 分支下,设置 format!='auto' 即表示允许跨格式转码(例如 'webp'/'avif')。插件会安全地改名并替换文本资产中的引用。
  • 若你只想同格式压缩但不改扩展名,设置 format:'auto' 即可。

🧠 Defaults & Options | 默认与选项

  • format: 'auto'(默认) → 同扩展名压缩;不变更后缀
  • transcode: false(默认) → 仅当设为 true 并 format≠原扩展名时才跨格式
  • quality: 80(默认)
  • resize: { maxWidth?, maxHeight?, fit? }(Vite/Webpack 同)
  • cache.enabled: true(默认)
  • dev.enabled: false(默认)
  • build.enabled: true(默认)

🖼️ AVIF Transcode | AVIF 转码

Why AVIF? Generally higher compression efficiency than WebP at similar perceptual quality. Recommended quality range: 45–75 (start with 70). AVIF decoding is well supported on modern browsers.

为什么选择 AVIF?通常在相近主观质量下,AVIF 的压缩率高于 WebP。建议质量范围:45–75(推荐 70 起步)。现代浏览器支持良好。

Enable in Vite:

rustyPic({ format: 'avif', transcode: true, quality: 70 })

Enable in Webpack:

new RustyPicWebpackPlugin({ format: 'avif', quality: 70 })

Compatibility tip: for older browsers, provide fallbacks via or server-side negotiation.

兼容性提示:对旧浏览器可通过 多源或服务端协商提供回退格式。

Example HTML pattern:

<picture>
  <source type="image/avif" srcset="/assets/sample.avif" />
  <source type="image/webp" srcset="/assets/sample.webp" />
  <img src="/assets/sample.png" alt="image" />
</picture>

📊 Example Size Comparison | 示例体积对比

Below numbers are measured on the sample image in this repo (public/卡片.png) with default settings (WebP q=80, AVIF q=70). Actual results vary by image content.

下表为本仓库示例图(public/卡片.png)在默认设置下的测量结果(WebP q=80,AVIF q=70),实际结果会因图片内容而异。

| Format | Size | Reduction | |-------:|-----:|----------:| | PNG (original) | 3.83 MB | – | | WebP | 226.49 KB | 94.4% | | AVIF | 225.39 KB | 94.4% |


🛠️ Runtime Backends | 运行后端

  • Node builds: sharp is used to perform real compression (jpeg/webp/avif/png). This ensures stable, fast build-time optimization and large size reductions.

  • Browser/WASM: the library exposes a WASM path (with Canvas fallback) for browser-side usage; this is independent from the build pipeline integration.

  • Node 构建:采用 sharp 实现真实压缩,稳定高效,体积下降显著。

  • 浏览器/WASM:库在浏览器侧可走 WASM(带 Canvas 兜底),与构建期集成相互独立。


🧪 Integration Tests | 集成测试

We ship runnable integration tests (generated into tests/.tmp) to verify both pipelines:

  • Vite: pnpm run test:int:vite
  • Webpack: pnpm run test:int:webpack

项目内提供可运行的集成测试(生成到 tests/.tmp)以验证两套管线:

  • Vite:pnpm run test:int:vite
  • Webpack:pnpm run test:int:webpack

📚 Programmatic API | 编程接口

Compress a single file (browser example):

import { rustyPic } from '@fe-fast/rusty-pic';
const file = document.querySelector('input[type="file"]').files[0];
const result = await rustyPic.compress(file, { format: 'webp', quality: 80 });
console.log('ratio', result.compressionRatio.toFixed(1), '%');

Batch compress:

const files = Array.from(document.querySelector('input[type="file"]').files);
const results = await rustyPic.compressBatch(files, { format: 'auto', quality: 85 }, (p) => {
  console.log(`progress ${p.completed}/${p.total}`);
});

Smart compress:

const r1 = await rustyPic.smartCompress(file);        // auto params
const r2 = await rustyPic.smartCompress(file, 100e3); // target 100 KB

Type signatures (simplified):

interface CompressionOptions {
  format?: 'webp' | 'jpeg' | 'png' | 'avif' | 'auto';
  quality?: number; // 1-100
  resize?: { width?: number; height?: number; fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside' };
  optimize?: { colors?: boolean; progressive?: boolean; lossless?: boolean };
}

🧰 CLI (optional) | 可选 CLI

npm install -g @fe-fast/rusty-pic
rusty-pic compress input.jpg -q 80 -f webp

CLI 为扩展能力,推荐优先采用 Vite/Webpack 构建集成以获得自动哈希与引用重写。


❓ FAQ

  • Q: Will hashed filenames and references be correct after compression/transcode?
    • A: Yes. The plugins operate within the bundler pipeline. Final filenames are content-hashed after compression, and references in JS/CSS/HTML are auto-updated.
  • Q: Is WebP/AVIF default?
    • A: No. Default is format='auto' and transcode=false (no rename). Enable transcode + set target format to produce WebP/AVIF.
  • Q: Any browser compatibility notes for AVIF?
    • A: AVIF requires modern browsers. Consider with multiple sources or server-side negotiation for older browsers.

🏗️ Development | 开发

pnpm install
pnpm run dev
pnpm run build

Requirements | 环境

  • Node.js 18+
  • (for WASM dev) Rust 1.70+ and wasm-pack

📄 License | 许可证

MIT


If this project helps you, please consider giving it a ⭐. 如果这个项目对你有帮助,欢迎点亮一个 ⭐!