開発者はPDFビューアを常に過小評価しています。単に「箱に入ったファイル」を扱うだけの単純な問題に見えるからです。バイトデータを取得し、コンポーネントにURLを指定すれば、それで終わりだと思いがちです。Vue.jsはほとんどのUI開発をこれほどまでにシンプルに感じさせますが、本番環境に耐えうるPDFビューアは、気づかないうちに開発スプリント全体を使い果たしてしまうような機能の一つです。私は2週間かけて、同じビューアを4つの異なる方法で構築しました。その試行錯誤を通じて、ある一つの結論に達しました。月曜日に選んだライブラリが、2ヶ月後にデバッグすることになるバグの種類を決定するのです。

古いチュートリアルの罠

ほとんどのガイドは、Vue 2が主流だった頃に最後に更新されたライブラリをいまだに推奨しています。開発者はREADMEをざっと読み、インストールコマンドを実行し、難しい部分は終わったと思い込みます。しかし実際には、本当の難関はまだ始まったばかりです。検索機能が必要になります。ブラウザのタブをクラッシュさせることなく、400ページの規約文書を扱わなければなりません。モバイルユーザーからは「ピンチ操作によるズームが使いにくい」という指摘が入るでしょう。READMEにこうした警告が書かれることはめったにありません。なぜなら、デモでは5ページの学術論文の最初の1ページしか表示されないからです。

4つのアプローチ

Vueにおける「唯一最高のPDFライブラリ」など存在しません。あるのは、ユーザーが実際に何をしようとしているかに基づいた「最適な選択肢」だけです。

PDF.js: DIYパス

MozillaのPDF.jsは、ほぼすべてのWebベースのビューアの基盤となっているエンジンです。これをVue 3アプリに導入するということは、単にコンポーネントをインストールすることではなく、一つのプロジェクトを引き受けることを意味します。getDocumentでドキュメントを取得し、各ページを<canvas>要素にレンダリングし、それらのキャンバスをテンプレートに組み込みます。1日目は生産性を感じているでしょう。しかし3日目には、ViteのバンドルやCORSヘッダーと上手く連携させるために、ワーカー(worker)スクリプトの設定に追われています。

ブラウザ標準のスクロールは10ページ程度なら問題ありません。しかし1,000ページになると動作が重くなるため、仮想スクロール(virtual scrolling)を構築することになります。次に、テキストが選択できないことに気づき、各キャンバスの上に透明なテキスト用のdivを重ねる作業が発生します。印刷がぼやけて見えるため、DPI設定やメディアクエリの調整に奔走します。モバイルでのピンチズームは、ブラウザ標準のジェスチャー操作と競合します。ドキュメントをまたいだ検索を実現するには、全ページのテキストを非同期で抽出・インデックス化し、メインスレッドをブロックせずに結果をキューイングするUIを構築する必要があります。CursorのようなAIコーディングアシスタントがボイラープレートを生成してくれたとしても、アーキテクチャの責任は依然としてあなたにあります。困難な課題が消えるわけではなく、あなたのコードベースへと移行してくるだけなのです。このパスが意味を成すのは、要件が極めて限定的である場合か、あるいは数週間の猶予があり、既存のライブラリの挙動を避けなければならない強力な理由がある場合に限られます。

vue-pdf-embed: 軽量パス

単にファイルを表示したいだけの時もあります。vue-pdf-embedは、ソースを受け取り、ページを垂直方向に積み重ねてレンダリングするVue 3コンポーネントです。インストールと統合は数分で終わります。生成された請求書やコンプライアンスレポートを表示する社内管理パネルなどには、これで十分なことが多いです。コンポーネントがキャンバスのレンダリングを処理するため、ユーザーはスクロールするだけで済みます。

トレードオフは、それ以外のすべてです。ツールバーも、ドキュメント検索も、サムネイルのサイドバーも、スクロールコンテナをなぞる以外のページナビゲーションもありません。ステークホルダーから「請求書番号で検索できる?」と聞かれた瞬間、わずか2時間の統合作業は、カスタム開発へと膨れ上がります。PDFが短く、対象が社内ユーザーで、インタラクションモデルが純粋な「読み取り専用のスクロール」である場合にこれを選んでください。

@tato30/vue-pdf: コントロールパス

このライブラリは、モノリシックなコンポーネントからコンポーザブル(composable)へと形を変えています。setupブロック内で呼び出すusePDFが公開されています。スクロール可能なドキュメント全体をレンダリングする代わりに、リアクティブなrefを通じて1ページずつ管理します。余計な手間のように聞こえるかもしれませんが、インターフェースに精密さが求められる場面では、これが解放感をもたらします。

保険金の請求審査ツールを想像してみてください。査定人がドキュメントのページを1枚ずつ確認し、「次へ」をクリックすると、システムが各閲覧イベントをログに記録するようなツールです。ここで連続スクロール型のビューアを使うのは、メタファーとして不適切です。必要なのは、ページレベルのコメント機能や、現在のページインデックスに直接紐付けられた承認ボタンを備えた、制御されたページャー(paginator)です。usePDFはページ数と現在のページをリアクティブなデータとして提供してくれるため、カスタムナビゲーションバーやプログレスインジケーターへの組み込みが自然に行えます。キャンバスの周囲のUI(chrome)は自分で構築する必要がありますが、低レベルなレンダリングのボイラープレートからは解放されます。これは、原稿をざっと読み飛ばすのではなく、ユーザーがページを1枚ずつ進めていくようなアプリに適しています。

Vue PDF Viewer: フルサービスパス

ビューアの機能を一から作り直すことが、本来の製品開発の妨げになる瞬間があります。Vue PDF Viewerは、ツールバー、テキスト検索、注釈、モバイル対応、仮想スクロールなどがエッジケースまでテスト済みの状態で提供される商用コンポーネントです。あなたの仕事は「発明」ではなく「設定」になります。デザインシステムに合わせてテーマを調整し、必要な機能を切り替えるだけで、アプリの差別化に直結する本来の業務に集中できます。

ライセンス料の初期費用は確かに発生しますが、検索インデックスや注釈レイヤーを再構築するためにエンジニアが2週間費やすコストもまた、無視できないものです。厳しい納期の中でプロダクションアプリをリリースする必要があり、ユーザーがデスクトップのPDFソフトウェアと同等の体験を求めている場合、これが最適なツールとなります。

インストールに本当にかかるコスト

最大の誤解は、npm install コマンドの実行が総コストだと考えてしまうことです。本当のコストは、インストールが終わった後に何を作るかにかかっています。軽量なライブラリは、初日は安上がりですが、検索バーが必要だと気づく20日目には高くつきます。自作(DIY)の道は、初日は無料ですが、モバイルのタッチターゲットや印刷用スタイルシートの修正に追われる60日目には高くつきます。商用ライブラリは初期費用がかかりますが、本来のビジネスロジックに充てられるはずの、数週間にわたるエンジニアリング時間を節約できます。

READMEが短くて親しみやすいからといって、ライブラリを選んではいけません。プロジェクトの要件に基づいて選んでください。サムネイルのサイドバー、テキスト検索、クライアントサイドの注釈が必要なら、フルサービスのソリューションが適しています。社内ダッシュボードでの簡単な領収書のプレビュー程度であれば、軽量な埋め込み型が適しています。

重要なポイント

どの Vue PDF ライブラリを採用するか決める前に、ユーザーが具体的に何をすべきかを書き出してください。単に短いドキュメントをスクロールするだけであれば、vue-pdf-embed で事足ります。制御されたワークフローの中でページをめくる必要があるなら、@tato30/vue-pdf を検討してください。ビジネス上重要なアプリ内で注釈、検索、印刷を行う必要があるなら、商用のビューアを購入しましょう。もし要件が非常に特殊で、かつ納期に余裕があるなら、数週間の時間を確保して PDF.js をベースに直接構築してください。PDFビューアは単なる「箱の中のファイル」ではありません。それは完全なドキュメント・インターフェースであり、どの構成要素を選ぶかが、今月リリースできるか、あるいは来四半期までずれ込むかを決定づけるのです。