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

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

npmのダウンロードトレンド
3 年
GitHub Starsランキング
統計詳細
パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
extract-zip17,983,331394-515年前BSD-2-Clause
adm-zip8,949,8642,143121 kB1491年前MIT
unzipper5,674,85246856.6 kB851年前MIT
node-unzip-231,46644-217年前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のようなミニマルなライブラリも有効です。要件に合わせて、無駄のない選択を心がけましょう。

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

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

  • adm-zip:

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

  • unzipper:

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

  • node-unzip-2:

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

extract-zip のREADME

extract-zip

Unzip written in pure JavaScript. Extracts a zip into a directory. Available as a library or a command line program.

Uses the yauzl ZIP parser.

NPM Uses JS Standard Style Build Status

Installation

Make sure you have Node 10 or greater installed.

Get the library:

npm install extract-zip --save

Install the command line program:

npm install extract-zip -g

JS API

const extract = require('extract-zip')

async function main () {
  try {
    await extract(source, { dir: target })
    console.log('Extraction complete')
  } catch (err) {
    // handle any errors
  }
}

Options

  • dir (required) - the path to the directory where the extracted files are written
  • defaultDirMode - integer - Directory Mode (permissions), defaults to 0o755
  • defaultFileMode - integer - File Mode (permissions), defaults to 0o644
  • onEntry - function - if present, will be called with (entry, zipfile), entry is every entry from the zip file forwarded from the entry event from yauzl. zipfile is the yauzl instance

Default modes are only used if no permissions are set in the zip file.

CLI Usage

extract-zip foo.zip <targetDirectory>

If not specified, targetDirectory will default to process.cwd().