adm-zip vs extract-zip vs node-unzip-2 vs unzipper
Node.jsでのZIPファイル操作ライブラリの比較
adm-zipextract-zipnode-unzip-2unzipper類似パッケージ:

Node.jsでのZIPファイル操作ライブラリの比較

adm-zipextract-zipnode-unzip-2unzipperはすべてNode.js環境でZIPファイルを扱うためのnpmパッケージです。これらのライブラリは、ZIPアーカイブの展開(解凍)や作成といった基本的な機能を提供しますが、設計思想、APIスタイル、ストリーム対応、メモリ使用量、エラーハンドリングなどの点で大きく異なります。フロントエンド開発者がビルドツールやCI/CDパイプライン内でアセットのダウンロード・展開を行う際などに、適切なライブラリを選定する必要があります。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
adm-zip02,161122 kB1441ヶ月前MIT
extract-zip0398-556年前BSD-2-Clause
node-unzip-2044-217年前MIT
unzipper047356.6 kB862年前MIT

ZIPファイル操作ライブラリ徹底比較:adm-zip vs extract-zip vs node-unzip-2 vs unzipper

Node.jsでZIPファイルを扱う必要があるとき、どのライブラリを選ぶべきか迷うことはよくあります。adm-zipextract-zipnode-unzip-2unzipperはどれもZIPを扱いますが、内部実装や使い勝手、メモリ使用量、サポート範囲が大きく異なります。この記事では、実際のコードを交えながら、それぞれの強みと弱みを明らかにします。

📦 基本的なZIP展開:シンプルさ vs 制御性

extract-zip — 展開専用のミニマリスト

extract-zipは「ZIPをフォルダに展開する」ことだけに焦点を当てたライブラリです。APIは非常にシンプルで、Promiseを返す非同期関数一つで完結します。

// extract-zip
const extract = require('extract-zip');

await extract('archive.zip', { dir: './output' });
// archive.zip の中身が ./output ディレクトリに展開される

ZIP作成やファイルリスト取得はできませんが、その分軽量で信頼性が高いです。Electronのドキュメントでも紹介されているほど、標準的です。

adm-zip — 同期的で多機能

adm-zipはZIPの読み込み・書き込み・編集を同期的に扱えるのが特徴です。ファイルリストの取得や個別ファイルの抽出も簡単です。

// adm-zip
const AdmZip = require('adm-zip');

const zip = new AdmZip('archive.zip');
zip.extractAllTo('./output'); // 全て展開

// 特定のファイルだけ取得
const entry = zip.getEntry('config.json');
if (entry) {
  const data = entry.getData(); // Buffer
}

ただし、同期APIのため大容量ZIPではメインスレッドをブロックし、メモリに全データを読み込むため、1GB以上のZIPには不向きです。

node-unzip-2 — Streamベースの細かい制御

node-unzip-2はStreamを使ってZIPを逐次処理します。メモリ使用量を抑えつつ、各ファイルのイベントをハンドリングできます。

// node-unzip-2
const fs = require('fs');
const unzip = require('node-unzip-2');

fs.createReadStream('archive.zip')
  .pipe(unzip.Parse())
  .on('entry', (entry) => {
    const fileName = entry.path;
    if (fileName === 'target.txt') {
      entry.pipe(fs.createWriteStream(`./output/${fileName}`));
    } else {
      entry.autodrain(); // 処理しないファイルは破棄
    }
  });

ただし、このパッケージはオリジナルのnode-unzipのフォークであり、最近の更新が少ないため、新規プロジェクトでは慎重に検討すべきです。

unzipper — 現代的なStream & Promise対応

unzipperはStreamとPromiseの両方をサポートし、柔軟な使い方が可能です。大容量ファイルにも対応し、API設計も洗練されています。

// unzipper — Promise版
const unzipper = require('unzipper');

await unzipper.Open.file('archive.zip')
  .then(d => d.extract({ path: './output' }));

// unzipper — Stream版
fs.createReadStream('archive.zip')
  .pipe(unzipper.Extract({ path: './output' }))
  .on('close', () => console.log('完了'));

さらに、directory()メソッドを使えば、ZIP内のファイルを仮想ディレクトリのように扱えます。

const directory = await unzipper.Open.file('archive.zip');
const file = directory.files.find(f => f.path === 'data.json');
const content = await file.buffer(); // Bufferとして取得

💾 メモリ使用量と大容量ファイル対応

  • extract-zip: 内部でyauzlを使用しており、Streamベースの展開を行うため、大容量ZIPでもメモリ効率が良いです。
  • adm-zip: 全ZIPコンテンツをメモリに読み込むため、大きなファイルではプロセスがクラッシュする可能性があります。
  • node-unzip-2: Stream処理なのでメモリ使用量は抑えられますが、エラーハンドリングがやや難しく、不安定なケースもあります。
  • unzipper: Stream処理を前提として設計されており、大容量ファイルでも安定して動作します。また、Open.file()は必要な部分だけを読み込む遅延評価方式を採用しています。

🔐 パスワード保護ZIPのサポート

  • adm-zip: パスワード付きZIPの作成は可能ですが、展開はサポートしていません
  • extract-zip: パスワード付きZIPには対応していません。
  • node-unzip-2: パスワード付きZIPの展開はサポートしていません。
  • unzipper: file.buffer({ password: '...' }) のように、一部のメソッドでパスワード指定による展開が可能です(ただし、すべての暗号化方式に対応しているわけではありません)。
// unzipper — パスワード付きZIP
const directory = await unzipper.Open.file('secure.zip');
const file = directory.files[0];
const data = await file.buffer({ password: 'secret' });

⚠️ メンテナンス状況と推奨度

  • extract-zip: 安定しており、シンプルな用途には今でも十分使えます。
  • adm-zip: 古くからあるライブラリで、バグフィックスはありますが、設計が古いため新規プロジェクトでは注意が必要です。
  • node-unzip-2: オリジナルのnode-unzipは非推奨となっており、このフォークも最近の更新が少ないため、新規プロジェクトでは使用を避けることを強く推奨します
  • unzipper: アクティブにメンテナンスされており、Stream/Promiseの両対応、メモリ効率、拡張性のバランスが非常に良いです。

🛠️ 実用シナリオ別の選定ガイド

シナリオ1: ビルド時に外部アセットを展開する(例:Chrome Driver)

  • 推奨: extract-zip
  • 理由: 単一の展開タスクで、依存が少なく信頼性が高い。
await extract(pathToZip, { dir: targetDir });

シナリオ2: ZIP内の設定ファイルだけを読み込んで処理する

  • 推奨: unzipper
  • 理由: 全展開せずに個別ファイルにアクセスでき、メモリ効率も良い。
const dir = await unzipper.Open.file('bundle.zip');
const config = JSON.parse((await dir.files.find(f => f.path === 'config.json').buffer()).toString());

シナリオ3: 大容量ログZIPを逐次処理してDBにインポート

  • 推奨: unzipper(Stream版)
  • 理由: メモリを圧迫せず、ファイルごとに処理を挟める。
fs.createReadStream('logs.zip')
  .pipe(unzipper.Parse())
  .on('entry', async (entry) => {
    if (entry.path.endsWith('.log')) {
      const lines = [];
      for await (const chunk of entry) {
        lines.push(chunk.toString());
      }
      await saveToDB(lines);
    } else {
      entry.autodrain();
    }
  });

シナリオ4: 小規模アプリでZIPを動的に生成してダウンロード

  • 推奨: adm-zip
  • 理由: ZIP作成が簡単で、同期APIが使いやすい。
const zip = new AdmZip();
zip.addFile('report.txt', Buffer.from('Hello'));
const buffer = zip.toBuffer();
res.send(buffer);

📊 まとめ:各ライブラリの特性比較

機能 / ライブラリadm-zipextract-zipnode-unzip-2unzipper
ZIP展開✅(同期)✅(非同期)✅(Stream)✅(Stream/Promise)
ZIP作成✅(限定的)
個別ファイルアクセス✅(Stream経由)✅(仮想ディレクトリ)
大容量ファイル対応❌(メモリ負荷高)
パスワード付きZIP作成のみ✅(展開のみ)
新規プロジェクト推奨△(小規模向け)✅(展開専用)❌(非推奨)✅(汎用)

💡 最終的なアドバイス

  • 「ただ展開したいだけ」なら extract-zip — 単純で信頼性が高い。
  • 「ZIPの中身を調べたり、一部だけ使いたい」なら unzipper — 柔軟で安全。
  • 「小さなZIPを動的に作る」なら adm-zip — 手軽だが、サイズに注意。
  • node-unzip-2 は避ける — 非推奨のフォークであり、代替手段が豊富にあるため。

現代のNode.jsプロジェクトでは、unzipperが最もバランスの取れた選択肢です。Stream対応、Promise対応、メモリ効率、そしてアクティブなメンテナンス — これらすべてを兼ね備えているからです。一方で、用途が極めて限定的であれば、extract-zipのようなミニマルなライブラリも有効です。要件に合わせて、無駄のない選択を心がけましょう。

選び方: adm-zip vs extract-zip vs node-unzip-2 vs unzipper

  • adm-zip:

    adm-zipはZIPファイルの読み書き両方に対応し、シンプルなAPIで同期的に操作できる点が特徴です。小規模なプロジェクトや、ZIP内のファイルリストを取得したり、特定のファイルだけを抽出したい場合に向いています。ただし、大容量ファイルではメモリ消費が大きくなる可能性があるため、注意が必要です。

  • extract-zip:

    extract-zipは「ZIPをディレクトリに展開する」ことに特化した軽量なライブラリです。非同期PromiseベースのAPIを提供し、ElectronやNext.jsなどの公式ドキュメントでも例として使われることがあります。ZIP作成機能はなく、読み取り専用ですが、用途が明確で安定しているため、単純な展開タスクには最適です。

  • node-unzip-2:

    node-unzip-2はオリジナルのnode-unzipのフォークで、Stream APIを活用してメモリ効率の良いZIP展開を実現します。大容量ZIPファイルを処理する必要があり、かつ細かい制御(例:ファイルごとのイベントハンドリング)が求められる場合に有効です。ただし、メンテナンス状況に注意が必要で、新規プロジェクトでは代替手段も検討すべきです。

  • unzipper:

    unzipperは現代的なStream対応ZIPライブラリで、読み取り・展開だけでなく、ZIPの作成やパスワード保護ZIPのサポート(一部)も備えています。PromiseとStreamの両方のインターフェースを持ち、大規模ファイルにも対応可能です。バランスの取れた機能とアクティブなメンテナンスにより、多くのユースケースで推奨される選択肢です。

adm-zip のREADME

ADM-ZIP for NodeJS

ADM-ZIP is a pure JavaScript implementation for zip data compression for NodeJS.

Build Status

Installation

With npm do:

$ npm install adm-zip

Electron file system support described below.

What is it good for?

The library allows you to:

  • decompress zip files directly to disk or in memory buffers
  • compress files and store them to disk in .zip format or in compressed buffers
  • update content of/add new/delete files from an existing .zip

Dependencies

There are no other nodeJS libraries that ADM-ZIP is dependent of

Examples

Basic usage

var AdmZip = require("adm-zip");

// reading archives
var zip = new AdmZip("./my_file.zip");
var password = "1234567890";
var zipEntries = zip.getEntries(); // an array of ZipEntry records - add password parameter if entries are password protected

zipEntries.forEach(function (zipEntry) {
    console.log(zipEntry.toString()); // outputs zip entries information
    if (zipEntry.entryName == "my_file.txt") {
        console.log(zipEntry.getData().toString("utf8"));
    }
});
// outputs the content of some_folder/my_file.txt
console.log(zip.readAsText("some_folder/my_file.txt"));
// extracts the specified file to the specified location
zip.extractEntryTo(/*entry name*/ "some_folder/my_file.txt", /*target path*/ "/home/me/tempfolder", /*maintainEntryPath*/ false, /*overwrite*/ true);
// extracts everything
zip.extractAllTo(/*target path*/ "/home/me/zipcontent/", /*overwrite*/ true);

// creating archives
var zip = new AdmZip();

// add file directly
var content = "inner content of the file";
zip.addFile("test.txt", Buffer.from(content, "utf8"), "entry comment goes here");
// add local file
zip.addLocalFile("/home/me/some_picture.png");
// get everything as a buffer
var willSendthis = zip.toBuffer();
// or write everything to disk
zip.writeZip(/*target file name*/ "/home/me/files.zip");

// ... more examples in the wiki

For more detailed information please check out the wiki.

Electron original-fs

ADM-ZIP has supported electron original-fs for years without any user interractions but it causes problem with bundlers like rollup etc. For continuing support original-fs or any other custom file system module. There is possible specify your module by fs option in ADM-ZIP constructor.

Example:

const AdmZip = require("adm-zip");
const OriginalFs = require("original-fs");

// reading archives
const zip = new AdmZip("./my_file.zip", { fs: OriginalFs });
.
.
.