ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 26

  1. Blog

Squoosh vs Sharp: 483ms vs 291ms Encode

@jsquash/jpeg 1.6.0 (Squoosh mozjpeg WASM) vs sharp 0.35.5 mozjpeg on one 1920×1080 JPEG → q80 encode from pre-decoded RGBA. Warm medians (7 rounds after 1 warm-up): Squoosh WASM 483 ms / 675,247 B vs sharp mozjpeg 291 ms / 546,546 B (~1.7×). Context: sharp decode+encode mozjpeg 303 ms; sharp libvips jpeg from raw 23 ms / 675,714 B. Fixture /workspace/bench-squoosh-sharp/. @squoosh/lib 0.5.3 fails on Node 22.

Aditya Challa·5 October 2026·4 min read

Hands-on
On this page
  1. What I tested
  2. How wide was the encode gap?
  3. Does Squoosh ever win this call?
  4. Should you switch image libraries?
  5. Sources
  6. Related

I encoded one 1920×1080 photo at JPEG quality 80 seven times on this box: Squoosh mozjpeg WASM (@jsquash/jpeg 1.6) median 483 ms (675 KB out), sharp 0.35 mozjpeg from the same raw RGBA median 291 ms (547 KB out) — about 1.7× faster and ~19% smaller.

Short answer: for Node pipelines that can load a native binding, sharp won this encode. Squoosh WASM still fits browser or edge runtimes that refuse native addons. 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:26–00:28 IST.
  • Versions: @jsquash/jpeg 1.6.0 (Squoosh mozjpeg WASM encoder); sharp 0.35.5; Node 22.20.0. @squoosh/lib 0.5.3 installed but throws on Node 22 (navigator property), so I drove the same Squoosh codec through @jsquash/jpeg with the WASM binary preloaded.
  • Fixture: /workspace/bench-squoosh-sharp/. Source src-1920.jpg is a 1920×1080 JPEG (~981 KB). Primary task: encode JPEG quality 80 from pre-decoded RGBA (encode-only wall times). Context: sharp decode+encode from the JPEG buffer with mozjpeg true/false.
  • Timing: performance.now around each encode; 1 warm-up each, then 7 interleaved rounds. Outputs written to out/ for size checks.
  • Findings: Squoosh WASM encode median 483 ms (449–510), out 675,247 B. sharp mozjpeg from raw median 291 ms (290–313), out 546,546 B. sharp decode+encode mozjpeg median 303 ms / 546,546 B. sharp libvips jpeg (mozjpeg false) from raw median 23 ms / 675,714 B.
  • One surprise: @squoosh/lib is dead on current Node; the maintained path is @jsquash/* with manual WASM init.
  • Not tested: browser Squoosh UI, WebP/AVIF, worker pools, Cloudflare Workers, Windows or macOS, serverless cold starts.

How wide was the encode gap?

PathMedian wallMin / MaxOutput JPEG
Squoosh WASM (@jsquash/jpeg) q80 encode-only483 ms449 / 510675,247 B
sharp 0.35 mozjpeg from raw RGBA q80291 ms290 / 313546,546 B
sharp mozjpeg decode+encode from JPEG (context)303 ms297 / 355546,546 B
sharp libvips jpeg from raw (context)23 ms22 / 29675,714 B

Same 1920×1080 source, same box. Headline numbers are encode-only from identical RGBA. sharp still finished faster than Squoosh WASM and wrote a smaller q80 file. For resize-first pipelines, see Sharp vs Jimp. For gulp-plugin minify, see Sharp vs imagemin. For build minify cousins, see terser vs esbuild/swc minify.

Does Squoosh ever win this call?

Yes, when you cannot ship a native sharp binary: browser tabs, some edge runtimes, or locked-down CI images. @jsquash/jpeg still needs a WASM init step on Node 22. On this Linux box with a normal sharp install, sharp mozjpeg was the default.

Treat this post as Squoosh mozjpeg WASM vs sharp mozjpeg on one JPEG q80 encode, not a full codec survey. libvips jpeg (mozjpeg false) was far faster (~23 ms) at a larger file — that trade-off belongs in a separate call.

Should you switch image libraries?

SituationMy pick
Node CI or server that can install sharpsharp
Browser or no-native-addon runtimeSquoosh / <br/>jsquash
Need smaller q80 JPEGs in Nodesharp mozjpeg
Need resize + encode in one stepsharp
Watching asset budgets after imagesPair with size-limit vs bundlesize and Vite vs Parcel​
Already on Astro/Vite using sharpStay; do not add Squoosh beside it

Bottom line: on one 1920 photo at q80, Squoosh WASM returned in 483 ms median with a 675 KB file while sharp mozjpeg from the same raw needed 291 ms and 547 KB. Who should not switch: teams stuck without native addons who already ship in the browser.

How this was made: I reused a 1920×1080 JPEG on the ShopperCove box, preloaded Squoosh mozjpeg WASM via @jsquash/jpeg, timed interleaved encode rounds against sharp 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://github.com/GoogleChromeLabs/squoosh
  • https://github.com/jamsinclair/jSquash
  • https://www.npmjs.com/package/@jsquash/jpeg
  • https://sharp.pixelplumbing.com/
  • https://www.npmjs.com/package/sharp

Related

  • https://www.shoppercove.com/blog/sharp-vs-jimp
  • https://www.shoppercove.com/blog/sharp-vs-imagemin
  • https://www.shoppercove.com/blog/size-limit-vs-bundlesize
  • https://www.shoppercove.com/blog/terser-vs-esbuild-swc-minify
  • https://www.shoppercove.com/blog/vite-vs-parcel
  • https://www.shoppercove.com/blog/swc-vs-esbuild-babel
  • https://www.shoppercove.com/blog/svgo-vs-svgr
  • https://www.shoppercove.com/blog/source-map-explorer-vs-webpack-bundle-analyzer
squooshsharpjpegmozjpegwasmnode.jsbenchmarkimage optimization

Lab evidence

What I found running this

Hands-on on ShopperCove box 6 Oct 2026 ~00:26–00:28 IST (8 vCPU Intel Xeon / 15 GB shared Linux, Node 22.20.0). @jsquash/jpeg 1.6.0 (Squoosh mozjpeg WASM; @squoosh/lib 0.5.3 fails on Node 22) vs sharp 0.35.5. Fixture /workspace/bench-squoosh-sharp/: src-1920.jpg 1920×1080 JPEG ~981 KB; encode JPEG q80 from pre-decoded RGBA. 1 warm-up + 7 interleaved rounds. Medians Squoosh WASM 483 ms (449–510) / 675,247 B vs sharp mozjpeg from raw 291 ms (290–313) / 546,546 B (~1.7×). Context sharp decode+encode mozjpeg 303 ms; sharp libvips jpeg from raw 23 ms / 675,714 B. Raw: /workspace/bench-squoosh-sharp/res-squoosh-sharp.json. Not tested: browser Squoosh UI, WebP/AVIF, workers, Cloudflare Workers, Windows/macOS, serverless cold starts. No affiliate.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • 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/.

    5 Oct 2026

  • 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 73

    volta vs fnm: Should You Switch? 14ms vs 17ms

    volta 2.0.2 vs fnm 1.39.0 switching Node 20.19.2 ↔ 22.14.0: session A-then-B median 13.9 ms vs 17.0 ms; steady node -v 7.4 ms vs 6.4 ms (direct 4.7 ms).

    5 Oct 2026

On this page

  1. What I tested
  2. How wide was the encode gap?
  3. Does Squoosh ever win this call?
  4. Should you switch image libraries?
  5. Sources
  6. Related
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove