はじめに
Webアプリケーションでのドキュメント表示って、意外と面倒なんですよ。
正直なところ、PDFをブラウザで表示するだけなら<iframe>で済ませることもできる。でも、ズームやページ送り、検索機能、注釈...と要件が増えていくと、途端に複雑になってくる。
GitHubで2,700スター以上を獲得しているEmbed-PDFは、そういった悩みを解決してくれるライブラリです。フレームワーク非依存でReact、Vue、Svelteにも対応。MITライセンスなので商用利用も問題なし。
30代になって思うのは、「車輪の再発明」に時間を使うより、信頼できるライブラリを活用する方が賢いということ。
Embed-PDFとは
Embed-PDFは「The ultimate Open Source PDF viewer for JavaScript」を謳うPDFビューアライブラリです。
特徴的なのは、2つの統合方法を提供している点。既製のビューアコンポーネントをそのまま使うか、ヘッドレスライブラリで完全カスタマイズするか選べます。
現在のバージョンは2.1系で、10人以上のコントリビューターが開発に参加。1,400以上のコミットがあり、活発にメンテナンスされています。
特徴・メリット
1. フレームワーク非依存
これ、意外と重要なんですよ。React専用、Vue専用のライブラリだと、プロジェクトによって使い分けが必要になる。
Embed-PDFはバニラJavaScriptはもちろん、React、Vue、Svelte、Preactに対応。どのプロジェクトでも同じ知識で対応できます。
2. 注釈機能が充実
PDFを表示するだけじゃなく、注釈をつけたいケースってありますよね。
Embed-PDFは以下の注釈機能を標準サポート:
- ハイライト
- 付箋(スティッキーノート)
- フリーテキスト
- インク描画
契約書のレビューとか、図面のチェックとか、実務で使えるレベルの機能が揃っています。
3. 真正な墨塗り機能
個人的には、これが一番刺さる機能です。
普通の「墨塗り」は見た目だけ黒く塗って、実際のデータは残っていることが多い。Embed-PDFの墨塗りは内容を実際に削除するので、セキュリティ的にも安心。
個人情報を含むドキュメントを扱う場合、これは必須機能ですね。
4. 軽量でパフォーマンスが良い
仮想スクロールを採用していて、大量ページのPDFでもスムーズに動作。プラグインアーキテクチャなので、使わない機能はツリーシェイクで除外できます。
コスパ的に、バンドルサイズを気にするプロジェクトでも導入しやすい。
5. 基本機能も網羅
- テキスト検索
- テキスト選択・コピー
- ズーム
- 回転
- ページナビゲーション
PDFビューアとして期待する機能は一通り揃っています。
インストール方法
既製のビューアを使う場合
npm install @embedpdf/snippet
シンプルにPDFを表示したいだけなら、これ一択ですね。
ヘッドレスライブラリを使う場合
npm install @embedpdf/core
UIを完全にカスタマイズしたい場合はこちら。
CDN経由で使う場合
npmを使わずに、CDNから直接読み込むこともできます。
<script async type="module">
import EmbedPDF from 'https://cdn.jsdelivr.net/npm/@embedpdf/snippet@2/dist/embedpdf.js';
</script>
プロトタイプや検証環境では、この方法が時短になる。
基本的な使い方
最小構成での表示
HTMLに2行書くだけでPDFビューアが動きます。
<!DOCTYPE html>
<html>
<head>
<title>PDF Viewer</title>
<style>
#viewer {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="viewer"></div>
<script type="module">
import EmbedPDF from 'https://cdn.jsdelivr.net/npm/@embedpdf/snippet@2/dist/embedpdf.js';
const viewer = EmbedPDF.init({
selector: '#viewer',
source: '/path/to/document.pdf'
});
</script>
</body>
</html>
これだけで動く。設定の少なさがQOL上がります。
Reactでの使用
import { useEffect, useRef } from 'react';
import EmbedPDF from '@embedpdf/snippet';
function PDFViewer({ pdfUrl }: { pdfUrl: string }) {
const containerRef = useRef<HTMLDivElement>(null);
const viewerRef = useRef<any>(null);
useEffect(() => {
if (containerRef.current && !viewerRef.current) {
viewerRef.current = EmbedPDF.init({
selector: containerRef.current,
source: pdfUrl
});
}
return () => {
if (viewerRef.current) {
viewerRef.current.destroy();
viewerRef.current = null;
}
};
}, [pdfUrl]);
return (
<div
ref={containerRef}
style={{ width: '100%', height: '80vh' }}
/>
);
}
export default PDFViewer;
Reactのライフサイクルに合わせてクリーンアップするのがポイント。
オプション設定
const viewer = EmbedPDF.init({
selector: '#viewer',
source: '/document.pdf',
// ページ設定
page: 1,
zoom: 'page-fit',
// UIカスタマイズ
toolbar: true,
sidebar: true,
// コールバック
onLoad: () => {
console.log('PDF loaded');
},
onError: (error) => {
console.error('Failed to load PDF:', error);
}
});
よく使うオプションはこの辺り。必要に応じて追加していけばいい。
ページ操作のAPI
// ページ移動
viewer.goToPage(5);
// 次のページ
viewer.nextPage();
// 前のページ
viewer.previousPage();
// ズーム操作
viewer.setZoom(150); // 150%
viewer.setZoom('page-fit');
viewer.setZoom('page-width');
// 回転
viewer.rotate(90);
プログラムからの操作も直感的。
実践的なユースケース
契約書ビューア
法務系のアプリケーションで、契約書を表示・注釈するケース。
const viewer = EmbedPDF.init({
selector: '#contract-viewer',
source: contractPdfUrl,
plugins: ['annotation', 'highlight'],
onAnnotationCreate: (annotation) => {
// 注釈をサーバーに保存
saveAnnotation(annotation);
}
});
注釈データをバックエンドで管理すれば、複数人でのレビューワークフローも実現できます。
請求書表示システム
ECサイトや業務システムで、請求書PDFを表示するケース。
const viewer = EmbedPDF.init({
selector: '#invoice-viewer',
source: invoicePdfUrl,
toolbar: {
download: true,
print: true,
zoom: true,
search: false // 請求書なので検索は不要
}
});
必要な機能だけ有効にして、UIをシンプルに保てます。
マニュアル・ドキュメント閲覧
社内ポータルで、業務マニュアルを閲覧するケース。
const viewer = EmbedPDF.init({
selector: '#manual-viewer',
source: manualPdfUrl,
sidebar: true, // 目次表示
search: true, // 検索機能
bookmark: true // しおり機能
});
// 検索APIを活用
document.getElementById('search-btn').onclick = () => {
const query = document.getElementById('search-input').value;
viewer.search(query);
};
長いドキュメントでも、検索と目次で必要な情報にすぐアクセスできる。
墨塗り処理
機密情報を含むドキュメントを外部共有する前に、墨塗りを行うケース。
const viewer = EmbedPDF.init({
selector: '#redaction-viewer',
source: sensitivePdfUrl,
plugins: ['redaction'],
onRedactionApply: async (redactions) => {
// 墨塗り適用後のPDFを取得
const redactedPdf = await viewer.export();
// 保存処理
downloadPdf(redactedPdf);
}
});
これ、意外と需要があるんですよね。個人情報保護の観点で。
PDF.jsとの比較
「PDF.jsでいいんじゃない?」という声もあると思います。
正直なところ、シンプルにPDFを表示するだけならPDF.jsで十分。ただ、以下のケースではEmbed-PDFの方が楽です:
| 機能 | PDF.js | Embed-PDF |
|---|---|---|
| 基本表示 | ○ | ○ |
| 注釈機能 | 要自作 | 標準搭載 |
| 墨塗り | 要自作 | 標準搭載 |
| UIコンポーネント | 要自作 | 選択可能 |
| セットアップ | 複雑 | シンプル |
個人的には、注釈や墨塗りが必要になった時点でEmbed-PDF一択ですね。
まとめ
Embed-PDFを導入して感じた変化:
- セットアップ: 2行のコードで動作。即座に検証できる
- 機能性: 注釈、墨塗り、検索まで標準装備
- 柔軟性: 既製UIとヘッドレスの2択で対応力が高い
- フレームワーク対応: React、Vue、Svelteどれでも使える
- ライセンス: MITで商用利用も安心
PDFビューアの実装で時間を溶かしていた人には、かなりおすすめです。特に業務アプリケーションで「ちゃんとしたPDFビューア」が必要になったとき、このライブラリの存在を知っているかどうかで開発効率が大きく変わります。
まだ試していない人は、まずCDN経由で軽く触ってみてください。「これでいいじゃん」ってなると思います。
