wkhtmltopdf を使って HTML を PDF へ変換していたのですが、canvas に JavaScript で描画しているはずの内容が全く表示されず、かなりはまったのでメモしておきます。
環境
実際には ASP.NET Core で Rotativa.AspNetCore を使っており、その中で HTML から PDF への変換に wkhtmltopdf が使われています。
- ASP.NET Core 2.2
- Rotativa.AspNetCore 1.1.1
- wkhtmltopdf 0.12.4
原因
結論から先に書くと、現時点で wkhtmltopdf は ES6 に対応していないため、ES6 で追加されたコードを書くと正しく実行されないようです。
具体的には、私の場合、以下のようなコードを書いていたことが原因でした、
- 変数宣言で
let
を使っていた codePointAt
で文字コードを取得していた
対策
let
ならば var
に置き換えるとかで簡単に対応可能ですが、中には対応が難しいものもあるかと思います。
一応対策として、babel を使って ES5 以前のコードにコンパイルするという手があります。
babel のインストール方法や使い方はググればいくらでも見つかるので割愛します。
ただ、私は JavaScript のコードも Razor で出力していたため、事前コンパイルせず(できず)、以下のようにブラウザ(この場合は wkhtmltopdf) 内でコンパイルせざるを得ませんでした。
<script type="text/babel">
// do something
</script>
そして、これだと処理速度が異常に遅くて使い物にならなかったので、結局 ES6 のコードを使わないように書き直して対応しました。
原因が分かるまでの経緯
「wkhtmltopdf canvas」などでググってみると、ChartJS が描画されないといった内容が多くヒットしますが、canvas を使っているのは同じはずなので、まずはそれを参考にいろいろ試してみました。
具体的には以下です。
canvas
をdiv
で括ってサイズを同じにする--no-stop-slow-scripts --javascript-delay 1000
を指定する(時間は適宜変更)
これらについては参考 URL やググってみるといろいろヒットするので、割愛します。
しかし、これらのことをやっても状況は変わらず、それ以上の情報はいくらググっても見つかりませんでした。
ただ、canvas
内の表示だけがおかしいので、JavaScript に問題があるのではないかということは推測できました。
デバッグが非常にやりづらく、仕方ないので少しずつ JavaScript コードを埋め込んで動作確認していたら、どうも途中から JavaScript のコードが実行されていないような感じでした。
そこでふと let
を見て、比較的最近追加された仕様だったなぁと思い、var
に変更したところ上手く描画されるようになりました。
いや、これ本当にはまった。
尚、wkhtmltopdf を現時点で最新の 0.12.6 に変更しても同様でした。
また、上述した
canvas
をdiv
で括ってサイズを同じにする--no-stop-slow-scripts --javascript-delay 1000
を指定する(時間は適宜変更)
ですが、私の環境では前者が不要でしたが、後者は必要でした。