Skip to content

Replacements for jszip ​

jszip creates and reads ZIP archives. Its dependencies are dated: it still pulls in pako 1, readable-stream 2 and the lie (Promise) and setimmediate polyfills.

fflate ​

fflate has no dependencies and can create and read ZIP archives synchronously or asynchronously. Instead of a JSZip object, an archive is a plain object that maps file names to Uint8Array contents. Nested objects become folders.

Creating an archive:

ts
import JSZip from 'jszip'
import { zipSync, strToU8 } from 'fflate'

const zip = new JSZip() 
zip.file('hello.txt', 'Hello World') 
zip.folder('images').file('pixel.png', pixel) 
const bytes = await zip.generateAsync({ type: 'uint8array' }) 
const hello = strToU8('Hello World') 
const bytes = zipSync({ 'hello.txt': hello, images: { 'pixel.png': pixel } }) 

Reading an archive:

ts
import JSZip from 'jszip'
import { unzipSync, strFromU8 } from 'fflate'

const zip = await JSZip.loadAsync(bytes) 
const text = await zip.file('hello.txt').async('string') 
const files = unzipSync(bytes) 
const text = strFromU8(files['hello.txt']) 

Folder entries show up in unzipSync results as empty files whose names end in /, like jszip's files keys. To extract only some files, pass a filter option, for example unzipSync(bytes, { filter: (file) => file.name.endsWith('.txt') }).

jszip stores files without compression unless you pass compression: 'DEFLATE', while fflate compresses at level 6 by default. Pass { level: 0 } to store files uncompressed.

zip and unzip are the asynchronous versions. They take a callback and run the work in a Web or Node worker, which adds some startup overhead, so they pay off for larger archives. For type: 'blob' or type: 'nodebuffer' output, wrap the bytes with new Blob([bytes]) or Buffer.from(bytes).

Released under the MIT License. (109fef9e)