はじめに
請求書や証明書、契約書といったPDF帳票を自動生成したい。そんなとき、多くの人がまず思い浮かべるのは「サーバー側でPDF生成ライブラリを動かす」という構成ではないでしょうか。ですが、外部APIに機密情報を含んだデータを送るのは避けたい、サーバーレス環境で重い依存関係を抱えたくない、といった悩みもつきものです。
PDF-Libは、そうした悩みをブラウザ・Node.js・Deno・React Nativeなど、あらゆるJavaScript環境の中だけで解決してくれるライブラリです。外部サービスに依存せず、PDFの作成から既存ドキュメントの編集まで完結できます。
PDF-Libとは
PDF-Libは「Create and modify PDF documents in any JavaScript environment」を掲げるオープンソースのPDF操作ライブラリです。新規PDFの作成はもちろん、既存PDFの読み込みと編集、フォームの作成・入力・フラット化まで、幅広い操作をJavaScript/TypeScriptだけで実現できます。
主な特徴
- どこでも動く - ブラウザ、Node.js、Deno、React Nativeなど、JavaScript環境を問わず同じAPIで動作します
- 既存PDFの編集が可能 - ゼロから作るだけでなく、既にあるPDFを読み込んでテキストや画像を追記・修正できます
- フォーム操作に対応 - テキストフィールドやチェックボックス、ラジオボタンなどのAcroFormを作成・入力・フラット化できます
- 依存が軽い - サーバーサイドのPDFレンダリングエンジンを別途用意する必要がなく、単体のパッケージとして完結します
インストール
npmでインストールします。
npm install pdf-lib
yarnやpnpmを使っている場合は、以下のコマンドでも導入できます。
yarn add pdf-lib
# または
pnpm add pdf-lib
CDN経由で読み込む場合は、UMDビルドをそのまま利用できます。
<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
基本的な使い方
まずは、新規PDFを作成してテキストを描画するシンプルな例です。
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib';
async function createPdf() {
// 新しいPDFドキュメントを作成
const pdfDoc = await PDFDocument.create();
// A4サイズのページを追加
const page = pdfDoc.addPage([595.28, 841.89]);
// 標準フォントを埋め込み
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
// テキストを描画
page.drawText('Hello, PDF-Lib!', {
x: 50,
y: 780,
size: 24,
font,
color: rgb(0.1, 0.1, 0.4),
});
// バイト列として保存
const pdfBytes = await pdfDoc.save();
return pdfBytes;
}
pdfBytesはUint8Arrayなので、Node.jsではファイルに書き出し、ブラウザではBlobに変換してダウンロードリンクを作成できます。
既存のPDFを読み込んで編集する場合も、手順はほとんど変わりません。
import { PDFDocument, rgb } from 'pdf-lib';
import fs from 'fs/promises';
async function editExistingPdf(inputPath: string) {
const existingBytes = await fs.readFile(inputPath);
const pdfDoc = await PDFDocument.load(existingBytes);
// 1ページ目を取得
const [firstPage] = pdfDoc.getPages();
const { height } = firstPage.getSize();
// 「確認済み」の印を追記
firstPage.drawText('確認済み', {
x: 50,
y: height - 50,
size: 18,
color: rgb(0.8, 0, 0),
});
return pdfDoc.save();
}
実践的なユースケース
実務でよくあるのが、テンプレートPDFにフォーム入力値を差し込んで帳票を自動生成するケースです。PDF-LibはAcroForm(PDFに埋め込まれたフォーム機能)の操作にも対応しているため、既存のフォーム付きPDFテンプレートに値を流し込んで、そのまま提出用PDFを作ることができます。
import { PDFDocument } from 'pdf-lib';
import fs from 'fs/promises';
async function fillInvoiceTemplate(templatePath: string, data: {
customerName: string;
invoiceNumber: string;
amount: string;
}) {
const templateBytes = await fs.readFile(templatePath);
const pdfDoc = await PDFDocument.load(templateBytes);
const form = pdfDoc.getForm();
// テンプレート側で定義済みのフィールド名に値をセット
form.getTextField('customerName').setText(data.customerName);
form.getTextField('invoiceNumber').setText(data.invoiceNumber);
form.getTextField('amount').setText(data.amount);
// 入力後は編集不可のフラット状態に変換
form.flatten();
const outputBytes = await pdfDoc.save();
await fs.writeFile('invoice-filled.pdf', outputBytes);
}
このように、あらかじめデザイナーが作ったフォーム付きテンプレートを用意しておけば、アプリケーション側は値を差し込んでフラット化するだけで完成します。帳票のレイアウトをコードで一から組む必要がないため、デザインと実装の分業がしやすくなるのもメリットです。
また、複数のPDFからページを抜き出して1つに結合する、既存の複数ページPDFから一部だけを取り出す、といった操作にも対応しています。契約書と添付資料をまとめて1つのPDFにする、といった業務でも活躍します。
まとめ
PDF-Libは、サーバーサイドの重量級PDFエンジンに頼らずとも、JavaScript環境だけでPDFの生成・編集・フォーム操作までを完結させられるライブラリです。ブラウザ完結のツールを作りたいときも、Node.jsのバッチ処理に組み込みたいときも、同じAPIで扱えるのは大きな強みです。
まずは今回紹介した新規作成とテキスト描画のサンプルを試し、慣れてきたら既存テンプレートへのフォーム入力やページ結合など、より実践的な機能にも触れてみてください。