archiver vs jszip vs pizzip
Creating and Manipulating Zip Archives in JavaScript
archiverjszippizzipSimilar Packages:

Creating and Manipulating Zip Archives in JavaScript

archiver, jszip, and pizzip are libraries used to create, read, and manipulate ZIP archives in JavaScript environments. archiver is a streaming interface designed primarily for Node.js server-side archive generation. jszip is a pure JavaScript library that works in both browsers and Node.js, focusing on in-memory manipulation of zip files. pizzip is a fork of jszip that aimed to address specific performance or compatibility issues, though its ecosystem presence is smaller. Choosing between them depends on whether you need server-side streaming, client-side manipulation, or specific legacy compatibility.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
archiver02,96039.6 kB158a month agoMIT
jszip010,357762 kB410-(MIT OR GPL-3.0-or-later)
pizzip062583 kB0a year ago(MIT OR GPL-3.0)

Archiver vs JSZip vs Pizzip: Streaming, Memory, and Environment Compared

When working with ZIP archives in JavaScript, the choice of library dictates your architecture. archiver, jszip, and pizzip solve similar problems but target different environments and memory models. archiver focuses on Node.js streaming, while jszip and pizzip focus on in-memory manipulation across browsers and servers. Let's compare how they handle common engineering tasks.

πŸ–₯️ Environment Support: Node.js vs Browser

archiver is built for Node.js.

  • It relies on Node.js stream modules.
  • Cannot run in the browser without heavy polyfills or bundler tricks that often break.
// archiver: Node.js only
const archiver = require('archiver');
const output = fs.createWriteStream('archive.zip');
const archive = archiver('zip');

archive.pipe(output);
archive.file('file1.txt', { name: 'file1.txt' });
archive.finalize();

jszip works everywhere.

  • Pure JavaScript with no Node.js dependencies.
  • Runs in browsers, Web Workers, and Node.js.
// jszip: Universal
const JSZip = require('jszip');
const zip = new JSZip();

zip.file('file1.txt', 'Hello World');
zip.generateAsync({ type: 'blob' }).then(content => {
  // Save in browser or Node
});

pizzip also works everywhere.

  • It is a fork of jszip so it inherits the universal runtime support.
  • API is nearly identical to jszip.
// pizzip: Universal
const PizZip = require('pizzip');
const zip = new PizZip();

zip.file('file1.txt', 'Hello World');
zip.generateAsync({ type: 'blob' }).then(content => {
  // Save in browser or Node
});

🧠 Memory Model: Streaming vs In-Memory

archiver uses streams.

  • Data flows through pipes without loading the whole file into RAM.
  • Essential for zipping gigabytes of data on a server.
// archiver: Streaming input
const archive = archiver('zip');

// Stream a large file directly into the zip
archive.append(fs.createReadStream('large-video.mp4'), { name: 'video.mp4' });
archive.finalize();

jszip loads everything into memory.

  • You must read the file into a buffer or string first.
  • Can crash browsers or servers if the ZIP is too large.
// jszip: In-memory input
const zip = new JSZip();

// Must read file content first
const content = fs.readFileSync('large-video.mp4');
zip.file('video.mp4', content);

zip.generateAsync({ type: 'nodebuffer' });

pizzip also loads everything into memory.

  • Same constraint as jszip since it shares the core architecture.
  • Not suitable for massive files on constrained devices.
// pizzip: In-memory input
const zip = new PizZip();

const content = fs.readFileSync('large-video.mp4');
zip.file('video.mp4', content);

zip.generateAsync({ type: 'nodebuffer' });

πŸ“– Reading Existing Archives

archiver is for creation only.

  • It does not support reading or unpacking existing ZIP files.
  • You need a different library like unzipper for extraction.
// archiver: No read support
// Cannot open an existing zip to inspect contents
// Must use a different package for extraction

jszip supports reading and writing.

  • You can load a ZIP file, modify it, and save it again.
  • Useful for updating archives without full re-creation.
// jszip: Read and modify
JSZip.loadAsync(existingZipBuffer).then(zip => {
  zip.file('new.txt', 'New Content');
  return zip.generateAsync({ type: 'blob' });
});

pizzip supports reading and writing.

  • Inherits the read capabilities from jszip.
  • Allows similar modification workflows.
// pizzip: Read and modify
PizZip.loadAsync(existingZipBuffer).then(zip => {
  zip.file('new.txt', 'New Content');
  return zip.generateAsync({ type: 'blob' });
});

βš™οΈ Compression Options

archiver allows fine-tuned compression.

  • You can set compression levels per file or globally.
  • Supports zlib options directly.
// archiver: Compression options
const archive = archiver('zip', {
  zlib: { level: 9 } // Max compression
});

archive.file('file.txt', { name: 'file.txt' });

jszip supports compression levels.

  • Configured during generation.
  • Trade-off between speed and file size.
// jszip: Compression options
zip.generateAsync({
  type: 'blob',
  compression: 'DEFLATE',
  compressionOptions: { level: 9 }
});

pizzip supports compression levels.

  • Matches jszip configuration API.
  • Same trade-offs apply.
// pizzip: Compression options
zip.generateAsync({
  type: 'blob',
  compression: 'DEFLATE',
  compressionOptions: { level: 9 }
});

⚠️ Maintenance and Risk

archiver is actively maintained.

  • It is the industry standard for Node.js archive creation.
  • Safe for long-term enterprise projects.

jszip is actively maintained.

  • Widely adopted with a large community.
  • Regular updates for security and bugs.

pizzip has limited activity.

  • It is a fork that may not receive timely security patches.
  • Using it introduces supply chain risk compared to jszip.
  • Only use if you have a specific patch need not in jszip.

🀝 Similarities: Shared Ground

While they target different layers, there is overlap in how they handle file data.

1. πŸ“‚ File Addition API

  • All three use a .file() method to add content.
  • Syntax is similar for basic string or buffer content.
// All three support basic file addition
archive.file('name.txt', 'content'); // archiver
zip.file('name.txt', 'content');     // jszip
zip.file('name.txt', 'content');     // pizzip

2. πŸ”’ Compression Standards

  • All use standard DEFLATE compression.
  • Archives created by one can usually be opened by standard OS tools.
// All produce standard .zip files
// Compatible with Windows Explorer, macOS Archive Utility, etc.

3. πŸ“ Metadata Support

  • Support setting file permissions and dates.
  • Important for preserving file attributes on extraction.
// jszip/pizzip example
zip.file('script.sh', content, { unixPermissions: '755' });

// archiver example
archive.file('script.sh', { mode: 0o755 });

πŸ“Š Summary: Key Differences

Featurearchiverjszippizzip
RuntimeπŸ–₯️ Node.js Only🌐 Browser + Node🌐 Browser + Node
Memory🌊 Streaming (Low RAM)🧠 In-Memory (High RAM)🧠 In-Memory (High RAM)
Read/Write✍️ Write OnlyπŸ”„ Read & WriteπŸ”„ Read & Write
Maintenanceβœ… Activeβœ… Active⚠️ Limited
Best ForServer Backups, Large ExportsClient Downloads, Small EditsLegacy JSZip Fork Needs

πŸ’‘ The Big Picture

archiver is the heavy lifter for servers πŸ—οΈ. Use it when you are on Node.js and need to zip large datasets without crashing your memory. It is the correct architectural choice for backend file processing.

jszip is the versatile tool for clients πŸ› οΈ. Use it when you need to zip files in the browser or handle small to medium archives in memory. It is the safest bet for universal JavaScript projects.

pizzip is a niche alternative πŸ•΅οΈ. Only consider it if you have a specific bug fix from its fork that jszip lacks and you can accept the maintenance risk. For most teams, the marginal gains do not justify the divergence from the main jszip ecosystem.

Final Thought: Match the tool to your runtime. If you are on the server streaming data, pick archiver. If you are in the browser or handling small files, pick jszip. Avoid pizzip unless you have a compelling, verified reason.

How to Choose: archiver vs jszip vs pizzip

  • archiver:

    Choose archiver if you are building a Node.js backend service that needs to stream large files directly into a ZIP archive without loading everything into memory. It is the standard choice for server-side file compression where performance and memory efficiency are critical. Avoid it for browser-based projects as it relies on Node.js streams.

  • jszip:

    Choose jszip if you need to create or read ZIP files directly in the browser or need a simple in-memory solution for Node.js. It is ideal for scenarios where users upload multiple files that need to be bundled client-side before download. Be cautious with very large files since it loads the entire archive into memory.

  • pizzip:

    Choose pizzip only if you have a specific requirement that jszip does not meet and you have verified its current maintenance status for your production needs. It is a fork of jszip and may offer niche fixes, but it carries higher risk due to a smaller community and potentially slower updates. For most new projects, jszip is the safer and more supported option.

README for archiver

Archiver

A streaming interface for archive generation

Visit the API documentation for a list of all methods available.

Install

npm install archiver --save

Quick Start

import fs from "fs";
import { ZipArchive } from "archiver";

// create a file to stream archive data to.
const output = fs.createWriteStream(__dirname + "/example.zip");
const archive = new ZipArchive({
  zlib: { level: 9 }, // Sets the compression level.
});

// listen for all archive data to be written
// 'close' event is fired only when a file descriptor is involved
output.on("close", function () {
  console.log(archive.pointer() + " total bytes");
  console.log(
    "archiver has been finalized and the output file descriptor has closed.",
  );
});

// This event is fired when the data source is drained no matter what was the data source.
// It is not part of this library but rather from the NodeJS Stream API.
// @see: https://nodejs.org/api/stream.html#stream_event_end
output.on("end", function () {
  console.log("Data has been drained");
});

// good practice to catch warnings (ie stat failures and other non-blocking errors)
archive.on("warning", function (err) {
  if (err.code === "ENOENT") {
    // log warning
  } else {
    // throw error
    throw err;
  }
});

// good practice to catch this error explicitly
archive.on("error", function (err) {
  throw err;
});

// pipe archive data to the file
archive.pipe(output);

// append a file from stream
const file1 = __dirname + "/file1.txt";
archive.append(fs.createReadStream(file1), { name: "file1.txt" });

// append a file from string
archive.append("string cheese!", { name: "file2.txt" });

// append a file from buffer
const buffer3 = Buffer.from("buff it!");
archive.append(buffer3, { name: "file3.txt" });

// append a file
archive.file("file1.txt", { name: "file4.txt" });

// append files from a sub-directory and naming it `new-subdir` within the archive
archive.directory("subdir/", "new-subdir");

// append files from a sub-directory, putting its contents at the root of archive
archive.directory("subdir/", false);

// append files from a glob pattern
archive.glob("file*.txt", { cwd: __dirname });

// finalize the archive (ie we are done appending files but streams have to finish yet)
// 'close', 'end' or 'finish' may be fired right after calling this method so register to them beforehand
archive.finalize();

Formats

Archiver ships with out of the box support for TAR and ZIP archives.