PDFファイルを手軽にHTMLに埋め込みたい
PDFファイルをHTMLに埋め込む場合、従来だと<iframe>
タグを使用するか、pdf.jsを使用する方法、Google Driveのプレビュー用URLを使う方法がありました。
ただし、それぞれ
-
<iframe>
タグを使用する方法 → PCのみ埋め込み可、スマホ非対応❌ - pdf.jsを使用する方法 → スマホに対応しているが、公式サイトからzipファイルを解凍し自分でサーバーに設置する必要がある(面倒)⚠️
- Google Driveのプレビュー用URLを使う方法 → 複数のPDFを埋め込むと挙動が不安定になってしまった&公式でサポートされているものなのか不明❌
という制限がありました。
詳しくはこちらの記事によくまとめられています。
pdf.jsを使うとしても、できることなら<script>
タグを一行差し込むだけで使えたら最高です。
pdf.js を WebComponent 化し、ライブラリとして配布
以上を踏まえて、<script>
タグを一行差し込むだけでpdf.jsが使えるライブラリを作りました!
使い方は次のようになります。
<!-- scriptタグでライブラリを読み込み -->
<script src="https://deno.land/x/embed_pdf@v1.2.0/mod.js" type="module"></script>
<!-- src属性にpdfのファイルパスを指定する -->
<embed-pdf src="./path/to/file.pdf"></embed-pdf>
scriptタグを読み込んだ後、<embed-pdf>
という名前のHTMLタグを設置することで、PDFを表示させることができます。
このHTMLファイルをブラウザで表示させると、以下のような感じでPDFファイルが埋め込まれているのが確認できます。
ライブラリの公開URLはこちら↓です。
ソースコードはGitHubで公開しています↓。
ライブラリ作成にあたっての技術選定
作成にあたって、以下の条件で技術選定しました。
条件1. npm install等なしで使えること
今回の自分のユースケースでは、導入対象のWebサイトは単純な静的ファイルサーバーであったため、npm等のツールチェーンや追加のビルド手順を(PDFを埋め込むためだけに)新たに導入したくないという事情がありました。
そのため、ライブラリはCDNからJSファイルを配信する形で提供することを検討しました。
条件2. 公開が簡単なこと
npmに公開する場合、アクセストークンの管理(数か月ごとに更新など)が必要になり、面倒なので、これ以外の選択肢を検討しました。
また、TypeScriptによる型チェックを行いながらビルド不要でリリースできる方法を検討しました。
条件3. バンドルサイズを小さくすること
今回はUI部品をライブラリ化していくので、Reactコンポーネントとして構築することも検討しました。
しかし、ライブラリのユーザーがReactを使用していない場合、このコンポーネントのためだけに追加で130KBをダウンロードさせることになってしまいます(これはVue.jsコンポーネントやPreactコンポーネントとして構築した時も同じ)。
そのため、これ以外の方法を検討しました。
条件4. 全モダンブラウザで利用可能なこと
ただしIE対応はしないことにしました。
以上の条件から、以下のような構成でライブラリを作成・配信しました。
- Denoを使用して開発
- ブラウザで動かすコードをそのまま型チェックにかけられる(=ビルドステップ不要)
-
https://deno.land/x で公開
- ここに公開しておけば、ブラウザから直接scriptタグで読み込める(CDN代わりになる)
- GitHub連携ができ、新しいリリースをGitHub上で作成すると自動で新しいバージョンがpublishされる
- npm publishで必要だったアクセストークンの管理等は不要
- ドキュメントも自動生成される
- WebComponentでコンポーネント化
- 結果、このライブラリ単独のサイズは2.8KBになったので充分許容範囲
ライブラリのサイズについては、依存関係のpdf.jsのサイズが大きいという問題があります。そこで、
- モバイル端末の場合 → pdf.jsを使って表示
- それ以外の場合 → ブラウザがPDF埋め込み表示に対応しているため、それを使用
という方法でロードサイズを抑えました。
まとめ
- PDFをHTMLに(全デバイス対応で)埋め込むのは意外と面倒
- scriptタグを1行差し込むだけでPDFが埋め込めたら最高→作った
- https://deno.land/x/embed_pdf で公開中
おまけ:車輪の再発明
実は、同様の思想のライブラリはこれまでに結構作成されています。
- A PDF Embed Web Component
- telecomsante/pdf-viewer
- streetturtle/pdf-element
- Creating a Web Component with PDF.js
- PDF viewer widget
- justinfagnani/pdf-viewer-element
しかし、6~8年前に開発が止まっている、古すぎてビルド手順が不明、最初の1ページしか表示できない、次ページボタンなどのUI要素は自分で作成する必要がある、pdf.jsは別途自分でダウンロードする必要がある、など今回のユースケースには合わなそうなものばかりでした。
そのため仕方なく自分が新たにライブラリを書いてリリースしておきました。