@zip.js/zip.js 2.8.26 → 2.8.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/BENCHMARKS.md +168 -0
  2. package/README.md +2 -2
  3. package/deno.json +1 -1
  4. package/dist/zip-core.js +1113 -574
  5. package/dist/zip-core.min.js +1 -1
  6. package/dist/zip-fs-core.js +1209 -622
  7. package/dist/zip-fs-core.min.js +1 -1
  8. package/dist/zip-fs-native.js +1270 -632
  9. package/dist/zip-fs-native.min.js +1 -1
  10. package/dist/zip-fs.js +1347 -686
  11. package/dist/zip-fs.min.js +1 -1
  12. package/dist/zip-legacy.js +1114 -575
  13. package/dist/zip-legacy.min.js +1 -1
  14. package/dist/zip-module.wasm +0 -0
  15. package/dist/zip-native.js +1116 -577
  16. package/dist/zip-native.min.js +1 -1
  17. package/dist/zip-web-worker-native.js +1 -1
  18. package/dist/zip-web-worker.js +1 -1
  19. package/dist/zip.js +1193 -631
  20. package/dist/zip.min.js +1 -1
  21. package/eslint.config.mjs +6 -1
  22. package/index-native.cjs +1270 -632
  23. package/index-native.min.js +1 -1
  24. package/index.cjs +1347 -686
  25. package/index.d.ts +2451 -2355
  26. package/index.min.js +1 -1
  27. package/lib/core/codec-pool.js +39 -1
  28. package/lib/core/codec-worker.js +130 -35
  29. package/lib/core/configuration.js +3 -0
  30. package/lib/core/constants.js +6 -0
  31. package/lib/core/io.js +55 -25
  32. package/lib/core/options.js +2 -0
  33. package/lib/core/streams/aes-crypto-stream.js +12 -12
  34. package/lib/core/streams/codec-stream.js +11 -5
  35. package/lib/core/streams/codecs/sjcl.js +1 -33
  36. package/lib/core/streams/common-crypto.js +4 -4
  37. package/lib/core/streams/zip-crypto-stream.js +25 -15
  38. package/lib/core/streams/zip-entry-stream.js +89 -5
  39. package/lib/core/streams/zlib-js/zlib-streams.min.js +1 -1
  40. package/lib/core/streams/zlib-wasm/zlib-streams.js +79 -56
  41. package/lib/core/streams/zlib-wasm/zlib-streams.wasm +0 -0
  42. package/lib/core/util/decode-cp437.js +1 -1
  43. package/lib/core/util/decode-text.js +2 -1
  44. package/lib/core/web-worker-base.js +12 -4
  45. package/lib/core/web-worker-inline-native.js +1 -1
  46. package/lib/core/web-worker-inline-wasm.js +1 -1
  47. package/lib/core/zip-fs.js +154 -55
  48. package/lib/core/zip-reader.js +185 -67
  49. package/lib/core/zip-writer.js +613 -376
  50. package/lib/core/zlib-streams-inline.js +1 -1
  51. package/lib/zip-core-reader.js +3 -1
  52. package/lib/zip-core-writer.js +1 -0
  53. package/package.json +20 -6
package/BENCHMARKS.md ADDED
@@ -0,0 +1,168 @@
1
+ # Benchmarks
2
+
3
+ A fair, reproducible comparison of **@zip.js/zip.js** against
4
+ [jszip](https://github.com/Stuk/jszip), [fflate](https://github.com/101arrowz/fflate)
5
+ and [archiver](https://github.com/archiverjs/node-archiver) on a set of realistic
6
+ workloads.
7
+
8
+ The numbers below are honest: zip.js wins clearly on some workloads and loses on
9
+ others. The goal is to show *where* each library is the right tool, and to give you a
10
+ harness you can re-run on your own hardware — the results are machine-specific and you
11
+ should not trust anyone's benchmark (including this one) without reproducing it.
12
+
13
+ > **TL;DR** — For compressing large or multiple entries, zip.js is the fastest option
14
+ > in the field, and it is the only one that parallelizes compression across CPU cores
15
+ > **without spawning a single Web Worker** — it lets the platform's native
16
+ > `CompressionStream` run on the threadpool while you simply issue concurrent `add()`
17
+ > calls. It also streams arbitrarily large files at a flat, low memory ceiling. For
18
+ > deflating thousands of tiny buffers in one shot, **fflate** remains the throughput
19
+ > and footprint champion.
20
+
21
+ ## Environment
22
+
23
+ | | |
24
+ |---|---|
25
+ | Machine | Apple M2, 8 cores (4 performance + 4 efficiency), 16 GB RAM |
26
+ | OS | macOS 26.5.1 (arm64) |
27
+ | Runtime | Node.js v24.12.0 |
28
+ | zip.js | 2.8.29 |
29
+ | jszip | 3.10.1 |
30
+ | fflate | 0.8.3 |
31
+ | archiver | 8.0.0 |
32
+
33
+ ## Method
34
+
35
+ - **Isolation.** Each `(library, operation, workload)` combination runs in its own
36
+ freshly-spawned Node process under `/usr/bin/time -l`, so there is no cross-library
37
+ GC or heap contamination and peak memory is a true per-library figure.
38
+ - **Timing.** `performance.now()` around the measured operation only. Every combination
39
+ runs **3 times**; the table reports the **median**.
40
+ - **Memory.** Peak resident set size (RSS) reported by `/usr/bin/time -l`. The "peak"
41
+ column is the delta over an empty-process baseline (~42 MB), i.e. the memory
42
+ attributable to the work.
43
+ - **Fair work.** All libraries compress at **DEFLATE level 6**. Output sizes are shown
44
+ so you can confirm each library did equivalent work. The corpus is generated from a
45
+ seeded PRNG, so every library sees byte-for-byte identical input.
46
+ - **zip.js modes.** zip.js is measured both **single-threaded** (apples-to-apples with
47
+ the single-threaded libraries) and with its **Web Worker** pool, so the worker
48
+ overhead is never hidden.
49
+
50
+ ## Compression — single process, single thread
51
+
52
+ Level-6 DEFLATE, one entry (or one batch) compressed in the main thread. This is the
53
+ apples-to-apples comparison against the single-threaded libraries.
54
+
55
+ | Workload | @zip.js/zip.js | jszip | fflate | archiver |
56
+ |---|--:|--:|--:|--:|
57
+ | Compressible text (20 MB) | **795 ms** | 1770 ms | 953 ms | 720 ms |
58
+ | Incompressible data (20 MB) | 446 ms | 883 ms | **306 ms** | 366 ms |
59
+ | Already-compressed media (20 MB) | 452 ms | 886 ms | **298 ms** | 358 ms |
60
+ | 5,000 files × ~2 KB | 845 ms | 887 ms | **287 ms** | 419 ms |
61
+
62
+ Peak memory for the same runs (Δ over baseline):
63
+
64
+ | Workload | @zip.js/zip.js | jszip | fflate | archiver |
65
+ |---|--:|--:|--:|--:|
66
+ | Compressible text (20 MB) | 92 MB | 65 MB | **60 MB** | 82 MB |
67
+ | Incompressible data (20 MB) | 141 MB | 93 MB | 106 MB | **83 MB** |
68
+ | Already-compressed media (20 MB) | 142 MB | 94 MB | 106 MB | **83 MB** |
69
+ | 5,000 files × ~2 KB | 266 MB | 270 MB | **102 MB** | 118 MB |
70
+
71
+ zip.js is fastest on compressible text and competitive with archiver elsewhere, at
72
+ roughly comparable compressed sizes. **fflate** is the clear winner on raw throughput
73
+ and footprint for incompressible data and for large numbers of tiny files — if that is
74
+ your workload, use fflate.
75
+
76
+ ## Parallelism & codec backends — 8 files × 8 MB, single process
77
+
78
+ This is the headline. The same 64 MB of compressible entries, compressed several ways
79
+ in a **plain Node process** (no worker threads unless noted). zip.js can select its
80
+ codec backend at runtime — native `CompressionStream`, the bundled WebAssembly zlib, or
81
+ a pure-JavaScript zlib port — and it can issue `add()` calls concurrently.
82
+
83
+ | Configuration | Median time | vs jszip |
84
+ |---|--:|--:|
85
+ | **zip.js — `CompressionStream`, concurrent `add()`** | **657 ms** | **8.8×** |
86
+ | fflate — async (its own worker pool) | 729 ms | 7.9× |
87
+ | archiver — Node zlib (libuv threadpool) | 2266 ms | 2.5× |
88
+ | zip.js — `CompressionStream`, sequential | 2453 ms | 2.3× |
89
+ | fflate — `zipSync` (single thread) | 3103 ms | 1.9× |
90
+ | zip.js — WASM zlib | 4176 ms | 1.4× |
91
+ | zip.js — pure-JS zlib | 4709 ms | 1.2× |
92
+ | jszip (pako, single thread) | 5758 ms | 1.0× |
93
+
94
+ **The point:** zip.js with the native `CompressionStream` goes from **2453 ms
95
+ sequential to 657 ms with concurrent `add()` — a 3.7× speedup — using no Web Workers at
96
+ all.** The native codec runs on the platform's threadpool, so independent entries
97
+ compress on multiple cores while your code stays on the main thread. That makes it the
98
+ fastest configuration measured, narrowly ahead of fflate's dedicated worker pool.
99
+
100
+ One honest caveat, visible in the table: **only the native `CompressionStream` backend
101
+ parallelizes this way.** The WASM and pure-JS backends run synchronously on the main
102
+ thread, so concurrent `add()` does not speed them up (4176 ms and 4709 ms whether
103
+ sequential or "parallel"). Use those backends when a native `CompressionStream` is
104
+ unavailable or when you need byte-identical zlib output; use the native backend when you
105
+ want this parallelism.
106
+
107
+ ## Decompression
108
+
109
+ Level-6 archives, read back and fully materialized. archiver has no unzip API, so it is
110
+ excluded.
111
+
112
+ | Workload | @zip.js/zip.js | jszip | fflate |
113
+ |---|--:|--:|--:|
114
+ | Compressible text (20 MB) | **65 ms** | 143 ms | 82 ms |
115
+ | 5,000 files × ~2 KB | 565 ms | 453 ms | **89 ms** |
116
+
117
+ zip.js has the fastest large-stream decompression. On thousands of tiny entries the
118
+ per-entry setup cost dominates and **fflate is dramatically faster and lighter** — again
119
+ the right tool when you are unpacking many small files.
120
+
121
+ ## Streaming a large file — 256 MB, disk → zip → disk
122
+
123
+ The input is streamed from disk and the archive is streamed back to disk; neither is
124
+ ever fully held in memory (for the libraries that support it).
125
+
126
+ | Library | Median time | Peak memory |
127
+ |---|--:|--:|
128
+ | archiver | 9183 ms | 111 MB |
129
+ | zip.js (workers) | 9893 ms | **99 MB** |
130
+ | zip.js (1 thread) | 10110 ms | **99 MB** |
131
+ | fflate | 10613 ms | 87 MB |
132
+ | jszip | 22358 ms | 527 MB |
133
+
134
+ zip.js, fflate and archiver all hold memory **flat** while streaming — zip.js peaks at
135
+ ~99 MB regardless of the 256 MB input, thanks to real backpressure through the
136
+ compression pipeline. **jszip buffers the entire file** and needs ~527 MB, at more than
137
+ twice the wall-clock time. If you process files that do not fit comfortably in memory,
138
+ avoid jszip.
139
+
140
+ ## When to pick which
141
+
142
+ - **Choose zip.js** for the fastest compression of large or multiple entries
143
+ (parallelism with no Web Workers), the fastest large-stream decompression, flat
144
+ low-memory streaming of huge files, and the broadest ZIP feature set in one library —
145
+ AES & ZipCrypto encryption, Zip64, split/multi-volume archives, and an optional Web
146
+ Worker pool.
147
+ - **Choose fflate** when you deflate thousands of tiny buffers in a single call and want
148
+ the smallest memory footprint and the highest raw synchronous throughput.
149
+ - **archiver** is a solid streaming compressor on Node but cannot read archives.
150
+ - **jszip** is convenient but the slowest here and buffers whole files in memory.
151
+
152
+ ## Reproduce
153
+
154
+ The harness lives in [`benchmarks/`](benchmarks/). It has no ties to the machine above;
155
+ run it on yours.
156
+
157
+ ```sh
158
+ cd benchmarks
159
+ npm install # jszip, fflate, archiver (zip.js is used from the repo)
160
+ npm run corpus # generate the deterministic datasets under .corpus/
161
+ node bench.js # the head-to-head tables (compress / decompress / disk streaming)
162
+ node bench-backends.js # the parallelism & codec-backend matrix
163
+ ```
164
+
165
+ Both scripts write JSON and a human-readable log to `benchmarks/results/`. Set
166
+ `RUNS=<n>` to change the number of repetitions (default 3). The datasets are generated
167
+ from a seeded PRNG (`benchmarks/lib/corpus.js`), so every run — and every library —
168
+ sees identical bytes.
package/README.md CHANGED
@@ -26,8 +26,8 @@ import {
26
26
  TextWriter,
27
27
  ZipReader,
28
28
  ZipWriter
29
- } from "@zip-js/zip-js";
30
- // Prefix "@zip-js/zip-js" with "jsr:" for Deno
29
+ } from "@zip.js/zip.js";
30
+ // "jsr:@zip-js/zip-js" for Deno
31
31
 
32
32
  // ----
33
33
  // Write the zip file
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zip-js/zip-js",
3
- "version": "2.8.26",
3
+ "version": "2.8.29",
4
4
  "exports": {
5
5
  ".": "./index.js"
6
6
  },