Skip to content

Migrating from imagemin

imagemin-rs keeps the familiar file and buffer APIs while collecting the core pipeline and built-in codec factories in one package. Migration can therefore start as an import change and then adopt stricter behavior deliberately.

Install the release candidate

sh
pnpm remove imagemin imagemin-svgo imagemin-gifsicle imagemin-optipng
pnpm add imagemin-rs@next

Keep any third-party imagemin plugins that are not replaced by a built-in factory. Optional dependencies must remain enabled because they contain the native binding and codec executables for the current platform.

Replace imports

ts
// Before
import imagemin from "imagemin";
import imageminMozjpeg from "imagemin-mozjpeg";
import imageminPngquant from "imagemin-pngquant";
import imageminSvgo from "imagemin-svgo";

// After
import imagemin, { mozjpeg, pngquant, svgo } from "imagemin-rs";

The file and buffer call shapes remain familiar:

ts
await imagemin(["images/**/*.{png,jpg,svg}"], {
  destination: "dist/images",
  plugins: [svgo(), pngquant(), mozjpeg({ quality: 80 })],
});

const output = await imagemin.buffer(input, {
  plugins: [mozjpeg({ quality: 80 })],
});

Third-party function plugins can remain in the same array. They receive a Node Buffer, run strictly in array order, and keep their normal error propagation.

Choose the intended codec profile

Existing pluginimagemin-rs factoryCompatibility boundary
imagemin-svgosvgo()Full SVGO 4 configuration path
svgm()Bounded native SVG profile; not full SVGO configuration
imagemin-gifsiclegifsicle()Compatible GPL sidecar
giflossless()Permissively licensed native lossless profile
imagemin-optipngoptipng()Option-shape compatibility through Oxipng; no byte-parity promise
imagemin-pngquantpngquant()Compatible GPL sidecar
imagemin-mozjpegmozjpeg()Compatible MozJPEG sidecar with documented upstream bug fixes
imagemin-jpegtranjpegtran()Coefficient-lossless output; strips EXIF, ICC, and comments
imagemin-webpwebp()Compatible static conversion with safer zero-value handling
imagemin-avifavif()Compatible 8-bit static conversion in an isolated worker

Read the individual codec guide before changing between compatibility and native profiles.

Review intentional differences

imagemin-rs makes several behaviors deterministic or explicit:

  • glob results are path-sorted and Windows backslashes are normalized;
  • destination extensions follow final file magic after format conversion;
  • unknown and out-of-range built-in options reject with ERR_IMAGEMIN_INVALID_OPTIONS;
  • concurrency defaults to at most four and can be set from 1 to 32;
  • AbortSignal stops new file scheduling and terminates built-in sidecars;
  • native tasks and non-cooperating third-party plugins can reject immediately on abort but cannot have their underlying CPU work forcibly preempted;
  • APNG, animated images, and multi-page inputs pass through where a static encoder would otherwise discard content.

These differences should be covered by application-level tests during migration instead of being treated as byte-for-byte implementation details.

Validate the migration

  1. Run the old and new pipelines over the same representative corpus.
  2. Compare decoded pixels, frames, metadata policy, and output extensions—not only file size or bytes.
  3. Exercise corrupt inputs and assert stable ImageminError.code values.
  4. Test a clean production install on every deployment platform.
  5. Preserve optional dependencies in bundlers, containers, and deployment pruning steps.

See Troubleshooting for native-load and sidecar diagnostics, and the Node API for the complete option surface.

Released under the MIT License.