Railsでwicked_pdf/wkhtmltopdf-binaryを使ってPDFファイルを出力する2021

RailsアプリでPDFファイルを出力することがあってそのときにハマったことをメモする

対象バージョン

wicked_pdf (2.1.0)
wkhtmltopdf-binary (0.12.6.5)

HTMLファイルでデバッグ的な何かをする

PDFでデザイン崩れを修正するのは一苦労なので、render時に show_as_html を渡す。 そうするとHTMLでデザインが見れるのでブラウザのdev toolsでCSSをいじって微調整ができる。

ただし!あくまでもブラウザで見えるだけであり、実際のPDFとはまた見え方が違うので過信しすぎてはいけない

respond_to do |format|
  format.pdf do
    render pdf: name, template: template, 
           show_as_html: params[:debug].present? && !Rails.env.production?
  end
end

Flexboxを使うときにはベンダープレフィックスが必要

github.com

タイトルの通りFlexboxを使うときはベンダープレフィックスが必要となる。これはwkhtmltopdfが古いブラウザエンジンを使っているため。

例えばこういう書き方が必要となってくる

.flex-row-container{
    display: flex;
    justify-content: space-between;
    align-items: center;

    display: -webkit-box;
    -webkit-box-pack: justify;
    -webkit-box-align: center;
}
.flex-column-container {
    display: flex;
    flex-direction: column;

    display: -webkit-box;
    -webkit-box-orient: vertical;
}

画像を埋め込む

Base64で埋め込むことになる。理由としては、画面から見えるときはいつもの癖で <img src="http://localhost:3000/some_image.jpg"> みたいにしてもできることはできるが、sidekiqなどの非同期処理で画像を埋め込むことを考慮すると(http://localhost:3000しても画像はみえないため)Base64で埋め込んだほうが良い。wicked_pdfがヘルパーを作っているので、assetからは以下のようにして読み出せる。

<%= image_tag wicked_pdf_asset_base64("some_image") %>

wicked_pdfではwebpacker用のヘルパーもあるが、上記の理由で使ってはいない。SGVファイルを埋め込むヘルパーがチームで用意されていたのでそれを使っている。

<%= embedded_svg(asset_pack_path("some_image.svg")) %>

def embedded_svg(filename, options = {})
  File.open("public/#{filename}", 'rb') do |file|
    doc = Nokogiri::HTML::DocumentFragment.parse file.read
    svg = doc.at_css 'svg'
    svg['class'] = options[:class] if options[:class].present?
    doc.to_html.html_safe
  end
end

マシンパワーで頑張ってもらう

ローカル環境で開発するときはやはり遅いのでマシンパワーで頑張ってもらう