csv-parse、csv-parser、fast-csv、papaparse はいずれも CSV(Comma-Separated Values)データを JavaScript オブジェクトや配列に変換するためのライブラリですが、設計思想や使用可能な環境、API のスタイルが大きく異なります。これらのライブラリは、Node.js 環境向け、ブラウザ向け、あるいはその両方で動作するものがあり、ストリーム処理に対応しているか、同期・非同期どちらのインターフェースを提供しているかなど、実際の開発要件によって最適な選択肢が変わります。特に、フロントエンド開発者はファイルアップロード後のブラウザ内パースや、大規模データの効率的な処理といったユースケースを考慮する必要があります。
フロントエンド開発で CSV ファイルを扱う際、「どのライブラリを使えばいいか?」という疑問に直面することがよくあります。一見どれも同じように見えますが、実際には設計思想、対応環境、API スタイル、保守状況が大きく異なります。この記事では、4つの主要な CSV パースライブラリを、実際のコードを交えながら深く比較します。
最初に重要なポイントとして、csv-parser は現在非推奨(deprecated)の可能性があります。npm 公式ページ(2024年時点)には「This package may no longer be maintained or supported.」という明確な警告が記載されています。新規プロジェクトでは使用を避け、代わりに papaparse や csv-parse を検討すべきです。
papaparse — ブラウザファースト設計papaparse は ブラウザでの使用を第一に設計されています。File オブジェクト、Blob、文字列のいずれからも直接パースでき、Web Worker を使って UI をブロックせずに処理できます。
// ブラウザ: File オブジェクトから直接パース
const fileInput = document.getElementById('csv-file');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
Papa.parse(file, {
header: true,
complete: (results) => console.log(results.data)
});
});
Node.js でも使えますが、主な強みはフロントエンドにあります。
csv-parse — Node.js 向けの高機能パーサーcsv-parse は Node.js 向けに最適化されており、ストリーム処理に完全対応しています。ブラウザでも動作しますが、バンドルサイズが大きくなる可能性があります。
// Node.js: ストリーム処理
const fs = require('fs');
const { parse } = require('csv-parse');
fs.createReadStream('data.csv')
.pipe(parse({ columns: true }))
.on('data', (row) => console.log(row))
.on('end', () => console.log('完了'));
fast-csv — Node.js 専用の堅牢な選択肢fast-csv は Node.js 専用であり、ブラウザ環境での使用は想定されていません。TypeScript との親和性が高く、スキーマバリデーションやデータ変換機能が充実しています。
// Node.js: Promise ベース
const fs = require('fs');
const csv = require('fast-csv');
const rows = await csv.parseString(fs.readFileSync('data.csv', 'utf8'), { headers: true }).toArray();
console.log(rows);
csv-parser — 非推奨のストリーム専用ライブラリcsv-parser は Node.js のストリーム API に特化していましたが、非推奨のため新規プロジェクトでの使用は避けてください。
// 非推奨の例(参考のみ)
fs.createReadStream('data.csv')
.pipe(csv())
.on('data', (row) => console.log(row));
csv-parse: stream().pipe(parse()) 形式で完全対応fast-csv: parseStream() でストリーム対応papaparse: ストリーム非対応(代わりに chunked parsing で擬似ストリーム処理)csv-parser: ストリーム専用(非推奨)// csv-parse: ストリーム
const parser = parse({ columns: true });
readableStream.pipe(parser);
// fast-csv: ストリーム
const stream = csv.parseStream(readableStream, { headers: true });
// papaparse: チャンク処理(ストリーム風)
Papa.parse(file, {
step: (row) => console.log(row.data), // 行ごとにコールバック
complete: () => console.log('終了')
});
papaparse: download: true 時を除き、基本はコールバック。Promise 化は自前でラップ必要csv-parse: parse() 関数で Promise 対応(v5+)fast-csv: .toArray() で Promise 対応// csv-parse: Promise
const records = await parse(csvString, { columns: true });
// fast-csv: Promise
const records = await csv.parseString(csvString, { headers: true }).toArray();
// papaparse: Promise 化(自前)
function parseCsv(file) {
return new Promise((resolve, reject) => {
Papa.parse(file, {
header: true,
complete: resolve,
error: reject
});
});
}
全ライブラリが header: true 相当の機能を提供していますが、実装方法が異なります。
// papaparse
Papa.parse(csv, { header: true });
// csv-parse
parse(csv, { columns: true });
// fast-csv
csv.parseString(csv, { headers: true });
// csv-parser (非推奨)
csv({ headers: true });
// papaparse
Papa.parse(csv, { delimiter: '\t' });
// csv-parse
parse(csv, { delimiter: '\t' });
// fast-csv
csv.parseString(csv, { delimiter: '\t' });
// csv-parser (非推奨)
csv({ separator: '\t' });
papaparse: error コールバックで詳細なエラー情報(行番号、タイプ)を提供csv-parse: on('error', ...) または Promise の catchfast-csv: エラーイベントまたは Promise の reject// papaparse
Papa.parse(csv, {
error: (error, file) => console.error('行', error.row, ':', error.message)
});
papaparse: 軽量(~15KB minified)、依存なし、Tree-shaking 可能csv-parse: 中程度(~30KB+)、Node.js 由来の依存ありfast-csv: やや重め(複数サブパッケージ)、TypeScript 型定義込みcsv-parser: 軽量だが非推奨フロントエンドアプリでは、バンドルサイズと初期ロード時間が重要です。papaparse はこの点で優れています。
✅ papaparse が最適
// 実際のアップロード処理
const handleFile = (file) => {
Papa.parse(file, {
header: true,
worker: true, // Web Worker で実行
step: (row) => updatePreview(row.data),
complete: () => showSuccess()
});
};
✅ csv-parse または fast-csv
fast-csv は TypeScript と相性が良い// csv-parse でのストリーム処理
fs.createReadStream('huge.csv')
.pipe(parse({ columns: true }))
.pipe(transformData())
.pipe(writeToDB());
✅ papaparse(ブラウザ)または csv-parse(Node.js)
// ブラウザ(同期)
const result = Papa.parse(csvString, { header: true });
// Node.js(同期)
const records = parse(csvString, { columns: true });
| 条件 | 推奨ライブラリ |
|---|---|
| ブラウザで CSV アップロード | papaparse |
| Node.js でストリーム処理 | csv-parse または fast-csv |
| TypeScript と連携 | fast-csv |
| 軽量で依存なし | papaparse |
| 非推奨を避ける | csv-parser は使用しない |
papaparse を試してください。使いやすく、機能も十分です。csv-parse の安定性か fast-csv の型安全性から選んでください。csv-parser は新規プロジェクトで使用しないでください。非推奨のため、セキュリティやバグ修正が保証されません。CSV パースは一見単純に見えますが、実際には改行、クォート、エンコーディング、不正データなど、多くの落とし穴があります。信頼できるライブラリを選ぶことで、こうした問題を効率的に回避できます。
csv-parse は Node.js 向けの高機能かつ安定した CSV パーサーで、ストリーム処理と同期/非同期 API の両方をサポートしています。Node.js バックエンドで大量の CSV を処理する必要がある場合や、細かいパース設定(区切り文字、クォート、コメント行など)を制御したい場合に最適です。ただし、ブラウザ環境ではバンドルサイズや互換性の観点から注意が必要です。
csv-parser は Node.js のストリーム API に特化したシンプルな CSV パーサーです。fs.createReadStream() と組み合わせて大規模ファイルをメモリ効率よく処理するシナリオに向いています。ただし、2023年時点で公式 npm ページに「メンテナンスされていない可能性がある」との注意書きがあり、新規プロジェクトでは代替手段の検討を強く推奨します。
fast-csv は Node.js 向けの CSV パース・生成ライブラリで、ストリームと Promise の両方のインターフェースを提供します。型安全性(TypeScript 対応)や柔軟なスキーマ定義、データ変換機能が特徴です。Node.js 環境で堅牢かつ拡張性の高い CSV 処理が必要な場合に適していますが、ブラウザ向けの使用は想定されていません。
papaparse はブラウザと Node.js の両方で動作する軽量で高速な CSV パーサーです。特にフロントエンド開発において、File API や Blob からの直接パース、プログレス表示、ワーカーによる非同期処理など、ユーザー体験を考慮した機能が充実しています。Web アプリで CSV アップロード機能を実装するなら、まず最初に検討すべきライブラリです。
The csv-parse package is a parser converting CSV text input into arrays or objects. It is part of the CSV project.
It implements the Node.js stream.Transform API. It also provides a simple callback-based API for convenience. It is both extremely easy to use and powerful. It was first released in 2010 and is used against big data sets by a large community.
Run npm install csv to install the full CSV module or run npm install csv-parse if you are only interested by the CSV parser.
Use the callback and sync APIs for simplicity or the stream based API for scalability.
The API is available in multiple flavors. This example illustrates the stream API.
import assert from "assert";
import { parse } from "csv-parse";
const records = [];
// Initialize the parser
const parser = parse({
delimiter: ":",
});
// Use the readable stream api to consume records
parser.on("readable", function () {
let record;
while ((record = parser.read()) !== null) {
records.push(record);
}
});
// Catch any error
parser.on("error", function (err) {
console.error(err.message);
});
// Test that the parsed records matched the expected records
parser.on("end", function () {
assert.deepStrictEqual(records, [
["root", "x", "0", "0", "root", "/root", "/bin/bash"],
["someone", "x", "1022", "1022", "", "/home/someone", "/bin/bash"],
]);
});
// Write data to the stream
parser.write("root:x:0:0:root:/root:/bin/bash\n");
parser.write("someone:x:1022:1022::/home/someone:/bin/bash\n");
// Close the readable stream
parser.end();
The project is sponsored by Adaltas, an Big Data consulting firm based in Paris, France.