but-unzip
small unzip library.
~704 bytes for Node,
and ~951^ bytes for browsers, before gzip.
^92.5%+ of browsers support the decompression API, which in 2025, is probably all your users.
If you really care about the last 7.5%, you can dynamically import pako
, adding ~20k: see below.
Usage
Install via your favorite package manager and import but-unzip
.
Has zero dependencies.
$ npm install but-unzip
$ npm install pako
This library returns zip entries synchronously, but only returns an entry's uncompressed bytes after calling .read()
, which'll give Uint8Array
or Promise<Uint8Array>
.
Naïve use
If there's a built-in function to inflate compressed files (like in Node or most browsers), you can use the code like:
import { iter } from 'but-unzip';
import * as fs from 'fs';
const bytes = fs.readFileSync('somezip.zip');
for (const entry of iter(bytes)) {
console.info(entry.name, entry.comment);
const bytes = await entry.read();
}
Provide inflate function
If you're worried about maximum compatibility:
import { unzip, inflateRaw as platformInflateRaw } from 'but-unzip';
import { inflateRaw as pakoInflateRaw } from 'pako/lib/inflate.js';
async function decompressUint8Array(zipBytes) {
const allEntries = unzip(zipBytes, platformInflateRaw || pakoInflateRaw);
}
Dynamically import inflate
You could use dynamic import()
instead to include pako
, but the intersection of users who:
- don't have the compression API
- don't support ESM imports
…are extremely high (e.g., IE11 and weird old browsers).
import { inflateRaw as platformInflateRaw } from 'but-unzip';
const inflateRaw = platformInflateRaw || (await import('pako/lib/inflate.js').inflateRaw);
Limitations
-
This library doesn't support ZIP64, but probably should.
But your browser (and Node) will probably not be happy to work with 4gb+ files, especially as this is not a streaming library (it just gives everything at once).
-
Like literally every zip library that exists, this only supports compression types 0 (store) and 8 (deflate).
Notes
-
In my testing with esbuild
, Pako's ESM bundling can be a bit broken, so importing "pako/lib/inflate.js" adds ~20k.
Importing pako
wholesale, even if you only use inflateRaw
, adds ~45k.
-
If you're handling user data and it could be really big, use a Worker
.
But also, the compression API is async
and doesn't block your main thread.
YMMV!