LaravelでPDFを出力してみた

2025.08.01 09:00
2025.08.01 12:54
LaravelでPDFを出力してみた

「LaravelでPDFを出したい」ってとき、mpdfとかdompdfがよく紹介されてるんだけど、CSSの細かいところが反映されなかったり、日本語フォントが変だったりで、ちょっと困ることありませんか?

今回、「もういっそ、HTML + CSS をそのままブラウザみたいにレンダリングしてPDF化したい!」と思って、Browsershotっていうライブラリを使ってみました。
結果的に、思ってたより簡単だし、かなり綺麗に出力できたので、その記録です。

なぜBrowsershotを使ったのか?

もともと mpdf を試してたんですが…

  • CSSグリッドやflexがうまく効かない
  • Google Fontsが使えない
  • レイアウト崩れが出る

という感じで「HTMLをPDFにできる」とはいえ、再現度がかなり低かったです。

それで調べてたら、「Browsershotならpuppeteer + headless ChromeでPDF化できる」っていう情報を発見。要するにChromeでレンダリング→そのままPDF出力というイメージらしく、期待が高まる。

この方法が使える環境・技術スタック

今回紹介するBrowsershotを使ったPDF出力は、以下のような技術スタック・環境で動作確認しました

  • MacOS 13.7
  • Laravel 11
  • Docker環境(arm64)
  • Node.js & npm(puppeteer動作用)
  • Chromium(headless Chrome)
  • Linuxベースの環境(Debian/Ubuntu系)

docker-composeを使ってローカル環境での導入をやってみました。
そのため、導入には Dockerfileの編集やビルド作業が発生します
また、puppeteerでChromeを動かすために一定のLinux知識フォントの導入が必要です。

※Xserverなどの共用レンタルサーバーや、npmが使えない環境ではこの方法は使えません。
ローカルやVPS、クラウド(EC2など)向けの内容です。

環境設定

1. ディレクトリ構成

まずは空のディレクトリで始めます

mkdir laravel-browsershot-pdf
cd laravel-browsershot-pdf

2. docker-compose

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: laravel-app
    volumes:
      - ./:/var/www
    ports:
      - "8080:80"
    working_dir: /var/www

3. Dockerfile

FROM php:8.3-fpm

# 基本パッケージ
RUN apt-get update && apt-get install -y \
    git unzip zip curl libzip-dev \
    libpng-dev libonig-dev libxml2-dev \
    libnss3 libatk1.0-0 libatk-bridge2.0-0 \
    libxss1 libasound2 libgbm-dev libxshmfence-dev libxrandr2 \
    fonts-ipafont-gothic \
    nodejs npm

# PHP拡張
RUN docker-php-ext-install zip pdo pdo_mysql

# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

# Puppeteer用Chromium
RUN npm install -g npm && \
    npm install puppeteer@21 && \
    node -e "require('puppeteer').createBrowserFetcher().download('138.0.0.0')"

Laravel設定

1. Laravelプロジェクト作成と起動

docker-compose run --rm app composer create-project laravel/laravel .
docker-compose up -d

2. Browsershotのインストール

docker-compose exec app composer require spatie/browsershot

3. コントローラー追加

docker-compose exec app php artisan make:controller PdfController
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\View;
use Spatie\Browsershot\Browsershot;

class PdfController extends Controller
{
    public function generate()
    {
        $html = View::make('pdf.sample', ['message' => 'こんにちは、Browsershot!'])->render();

        $pdfPath = storage_path('app/public/sample.pdf');

        Browsershot::html($html)
            ->format('A4')
            ->waitUntilNetworkIdle()
            ->savePdf($pdfPath);

        return response()->download($pdfPath);
    }
}

4. Bladeテンプレートを追加

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>サンプルPDF</title>
  <style>
    body { font-family: "IPA Pゴシック", sans-serif; padding: 40px; }
    h1 { color: #336699; }
  </style>
</head>
<body>
  <h1>{{ $message }}</h1>
  <p>これはBrowsershotで作成されたPDFです。</p>
</body>
</html>

5. ルートを設定

use App\Http\Controllers\PdfController;

Route::get('/pdf', [PdfController::class, 'generate']);

PDF出力

1. アクセスしてPDFを確認

ブラウザで以下にアクセスするとPDFのダウンロードが始まります。

http://localhost:8080/pdf

これで完成です!

というわけで、今回はBrowsershotを使ったPDF出力の方法をまとめてみました。
自分と同じように「どうすればいいんだろ?」と悩んでいた誰かの参考になればうれしいです。

今回は以上です!