ZIP compression that runs on the main thread freezes everything — animation, scrolling, clicks, typing. A Web Worker moves the work off-thread so the page stays alive. This instrument plots per-frame time live: a flat line is a responsive UI; a tall spike is the UI hung. Run the tests and watch which compressors spike.
| compressor | codec time | longest main-thread stall | janky frames (>50ms) |
output | verdict |
|---|
web-jszipp writer. The
worker rows load web-jszipp/worker-plugin, pass a worker backend to the normal
ZipWriter, and compare static module-worker and classic-worker scripts.zipSync) also runs on the main thread — included to show that "sync on main
thread" is the property that freezes the UI, regardless of library. fflate worker (zip(...),
async) ships its own inline Web Worker and transfers the buffer off-thread.CompressionStream('deflate-raw') is a bonus row: it runs the codec in native
browser code off the main thread with zero added bundle. It emits a raw DEFLATE stream, not a full
ZIP container, so its output size isn't directly comparable — it's here to show the cheapest off-thread path.requestAnimationFrame, so they freeze with the main thread. (A pure-CSS spinner can keep turning on
the compositor even while JS is hung, which would hide the problem.)
Testing your local JSZipp build instead of the published one? Replace the web-jszipp CDN URL in the
source with ../dist/jszipp.umd.js, ../dist/jszipp.worker-plugin.mjs, and
../dist/jszipp.worker.mjs. For compat builds use the matching
../dist/cr61ff58/ or ../dist/cr86ff68/ UMD plugin and classic worker script. Serve the
repo over HTTP (e.g. node scripts/serve-demo.mjs), since module/UMD/worker loading needs a real origin.