ChromeでPDF作り始めて十数か月の日々が流れた

はじめまして。フロントエンドエンジニアを名乗らせていただいております、MF KESSAIの井原です。 入社してもう1年以上経っているのですが、初めてのブログになります。

今回は入社して最初の仕事だった、PDFの作成にHeadless Chromeを使った話です。

経緯

自分が入社して最初の仕事は、wkhtmltopdfというツールを使って請求書のPDFを吐き出すというものでした。
このツールは名前の通りHTMLをPDFに変換するもので、Qt上のwebkit系ブラウザを用いているため、普段使っているブラウザで見る見た目に近いPDFを作ることができます。
ですが当時のwkhtmltopdfで利用しているブラウザは非常に古く、JavaScriptもES2015以降の書き方はもちろんできないですし、CSSもflexboxなんて便利なものもありませんでした。
さらには、改ページを制御するために要素の高さを取りたかったのですが、日本語が入ると表示されている高さとJavaScriptで取得する高さが倍以上違うという問題が起きました。
何が問題で起きているのか全く分からず、当初はある程度余裕を持って改ページするぐらいの苦肉の策で乗り切っていました。そのせいでたまに不必要なページが作られてしまうことがありました。

(補足)基本的には改ページは勝手によしなにしてくれます。ページを印刷した時とほぼ同じ動作です。ただ当時はテーブルを綺麗に分けたかったという目的があったためJavaScriptで制御することになりました。

そんな苦労をしている時公開されたのが、Headless Chromeでした。
最初はPDF作成に使えるとは思っていなくて、PhantomJS使わなくてもいいのかーぐらいの感情でこの記事を読んでいました。

そしたら記事内にPDFを作成するという項目が見えるじゃないですか。これはいけると思い、使い始めた次第です。

導入

Googleの記事内ではコマンドラインからPDF作成の実行をしていましたが、今回はDevTools Protocolを叩いて実行する形にしました。

動作の流れは、以下のようになります。

  1. 請求書HTMLを作成するスクリプトを走らせ、HTMLファイルを作成する
  2. スクリプトからChromeを立ち上げ、Chromeで対象のファイルを開く
  3. PDFをプリントする口を叩いてPDFを取得する

wkhtmltopdfと大きく違うところは最初の手順です。
wkhtmltopdfはテキスト自体を受け取る口がありましたが、Chromeの場合は一度ファイルに書き出してfile URI schemeでアクセスする必要があります。

DevTools Protocolを叩くライブラリは各言語で揃っているため、自分の環境に合わせて選択するといいと思います。(参考)
ちなみに弊社のメインで使われている言語はGoなので、Goのライブラリを採用しました。フロントエンドエンジニアもたまにGo書くよ!

ChromeでのPDF作成の利点

最新のCSSやJavaScriptが問題なく使えます。
そしてローカルで使っているChromeとほぼ一緒なので変な動作もしないですし、何よりデバッグが非常にやりやすいです。
Chromeで開いているページを印刷するとプレビューが表示されますが、それがそのままPDFと同じ見た目なので簡単に確認できます。

あと個人的にはmedia=printを初めてちゃんと意識して書くきっかけになったなという気持ちです。

終わりに

もう1年以上前に作った環境ですが、今も問題なく使えていますし導入してよかったと思っています。
おそらく今だとPuppeteerを使えると思いますし、Node on GAE SEならPuppeteer + Chromeの環境も整っているので、簡単に導入できる気がします。最近だとCloud FunctionsからPuppeteerを叩けるようになったという話もありますし、かなり楽に始められそうです。

もしPDF生成する必要が出てきたらこういう手もあるぞと選択の候補にでも入れば良いなと思います🙏