Plate 95
Sharp vs imagemin: 305ms vs 399ms Encode
sharp 0.35.5 vs imagemin 9.0.1 + imagemin-mozjpeg 10.0.0 on one 1920×1080 JPEG → JPEG q80 (no resize). Warm medians (7 rounds after 1 warm-up): sharp 305 ms / 546,546 B vs imagemin-mozjpeg 399 ms / 675,128 B (~1.3×). Context: sharp resize 800 q80 median 115 ms / 142,435 B. Fixture /workspace/bench-sharp-imagemin/.
Aditya Challa4 min read
I encoded one 1920×1080 JPEG at quality 80 seven times on this box: sharp 0.35 median 305 ms (547 KB out), imagemin-mozjpeg 10 median 399 ms (675 KB out) — about 1.3× slower and ~23% larger for the same q80 encode.
Short answer: for Node image pipelines that can load a native binding, sharp was the default here. imagemin still fits gulp-style plugin stacks that only minify already-sized assets. No affiliate links in this post.
What I tested
- Machine: 8 vCPU Intel Xeon / 15 GB RAM shared Linux cloud box, tested 6 Oct 2026 about 00:22–00:23 IST.
- Versions: sharp 0.35.5 (libvips / mozjpeg); imagemin 9.0.1; imagemin-mozjpeg 10.0.0; Node 22.20.0.
- Fixture: /workspace/bench-sharp-imagemin/. Source src-1920.jpg is a 1920×1080 JPEG (~981 KB). Primary task: JPEG encode quality 80 with no resize. sharp used mozjpeg:true; imagemin used imageminMozjpeg({quality:80}) via imagemin.buffer.
- Extra check: sharp resize width 800 + jpeg q80 (same geometry as my Sharp vs Jimp lab) for pipeline context only.
- Timing: performance.now around each encode; 1 warm-up each, then 7 interleaved rounds. Outputs written to out/ for size checks.
- Findings: sharp encode median 305 ms (min 298 / max 307), out 546,546 B. imagemin-mozjpeg median 399 ms (391–418), out 675,128 B. Ratio ~1.3× on wall clock. sharp resize+encode median 115 ms / 142,435 B at 800×450.
- One surprise: at the same nominal quality 80, imagemin-mozjpeg kept ~128 KB more than sharp's mozjpeg path on this photo.
- Not tested: PNG/WebP/AVIF, imagemin-pngquant, gulp wiring, Squoosh, concurrency, Windows or macOS, serverless cold starts.
How wide was the encode gap?
| Path | Median wall | Min / Max | Output JPEG |
|---|---|---|---|
| sharp 0.35 jpeg q80 (mozjpeg) | 305 ms | 298 / 307 | 546,546 B |
| imagemin-mozjpeg 10 q80 | 399 ms | 391 / 418 | 675,128 B |
| sharp resize 800 + jpeg q80 (context) | 115 ms | 112 / 143 | 142,435 B |
Same source buffer, same box, encode-only for the headline numbers. sharp also covers resize/crop in one chain; imagemin alone does not — that is a feature gap, not just a speed gap. For the pure resize comparison against a JS codec, see Sharp vs Jimp. For build minify cousins, see terser vs esbuild/swc minify and SWC vs esbuild vs Babel.
Does imagemin ever win this call?
Yes, when your repo is already a gulp or legacy plugin pipeline and you only minify files that are already at final dimensions. imagemin-mozjpeg dropped into that shape without a native sharp install. On this Linux box with a normal npm install, sharp was faster and smaller on the same q80 job, and it can resize in the same call.
I did not run Squoosh (@squoosh/lib); that path is a different maintenance story. Treat this post as sharp vs imagemin-mozjpeg on one JPEG q80 encode, not a full codec survey.
Should you switch image libraries?
| Situation | My pick |
|---|---|
| Node CI or server that can install sharp | sharp |
| Gulp/imagemin plugin stack, assets pre-sized | imagemin can stay |
| Need resize + encode in one step | sharp |
| High-volume thumbnail farm | sharp |
| Watching bundle/asset budgets after images | Pair with size-limit vs bundlesize and Vite vs Parcel |
| Already on Astro/Vite pipelines using sharp | Stay; do not add imagemin beside it |
Bottom line: on one 1920 JPEG at q80, sharp returned in 305 ms median with a 547 KB file while imagemin-mozjpeg needed 399 ms and 675 KB. Who should not switch: teams locked into an imagemin gulpfile that only touches final-size assets and cannot take a native addon.
How this was made: I reused a 1920×1080 JPEG on the ShopperCove box, installed sharp and imagemin-mozjpeg, timed interleaved encode rounds after a warm-up, recorded JSON medians and output bytes; the write-up was drafted with AI help and checked against that output.
Sources
- https://sharp.pixelplumbing.com/
- https://github.com/imagemin/imagemin
- https://github.com/imagemin/imagemin-mozjpeg
- https://www.npmjs.com/package/sharp
- https://www.npmjs.com/package/imagemin
Related
- https://www.shoppercove.com/blog/sharp-vs-jimp
- https://www.shoppercove.com/blog/size-limit-vs-bundlesize
- https://www.shoppercove.com/blog/swc-vs-esbuild-babel
- https://www.shoppercove.com/blog/terser-vs-esbuild-swc-minify
- https://www.shoppercove.com/blog/vite-vs-parcel
- https://www.shoppercove.com/blog/source-map-explorer-vs-webpack-bundle-analyzer
- https://www.shoppercove.com/blog/lightningcss-vs-postcss
- https://www.shoppercove.com/blog/rolldown-vs-rollup
Lab evidence
What I found running this
Hands-on on ShopperCove box 6 Oct 2026 ~00:22–00:23 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). sharp 0.35.5 (mozjpeg) vs imagemin 9.0.1 + imagemin-mozjpeg 10.0.0. Fixture /workspace/bench-sharp-imagemin/: src-1920.jpg 1920×1080 JPEG ~981 KB; encode JPEG q80 no resize. 1 warm-up + 7 interleaved rounds. Medians sharp 305 ms (298–307) / 546,546 B vs imagemin-mozjpeg 399 ms (391–418) / 675,128 B (~1.3×). Context resize 800 q80: sharp 115 ms / 142,435 B. Raw: /workspace/bench-sharp-imagemin/res-sharp-imagemin.json. Not tested: PNG/WebP/AVIF, pngquant, gulp, Squoosh, concurrency, Windows/macOS, serverless cold starts. No affiliate.
Related links
Plate 88
Sharp vs Jimp: 112ms vs 366ms Resize
sharp 0.35.5 vs Jimp 1.6.1 on one 1920×1080 JPEG → width 800 JPEG q80. Warm medians (7 rounds after 1 warm-up): sharp 112 ms / 142,435 B vs Jimp 366 ms / 269,590 B (~3.3×). Fixture /workspace/bench-sharp-jimp/.
5 Oct 2026
Plate 47
bun test vs Vitest: 136ms vs 1.67s on 300 Tests
bun test 1.4.2 vs Vitest 5.0.3 on 300 TypeScript tests in 60 files: warm wall medians 136 ms vs 1,673 ms (~12x); Vitest --no-isolate 765 ms (~5.6x). A 5-file vitest-API check (vi.fn, vi.mock, fake timers, spyOn, it.each, snapshot) passed 7/7 under Bun.
5 Oct 2026
Plate 46
esbuild-register vs jiti: 343ms vs 540ms Cold
esbuild-register 3.6.0 vs jiti 2.7.0 on a 61-file TypeScript graph: cold wall medians 343 ms vs 540 ms (~1.57x); after jiti disk cache warm, 185 ms vs esbuild-register 350 ms. Same printed result 970.
5 Oct 2026