Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Pdf Chrome Driver Laravel Package

breuer/laravel-pdf-chrome-driver

A Laravel PDF driver that turns Blade/HTML into PDFs using headless Chrome, so modern CSS, fonts, and layouts render faithfully. Register it as your PDF driver and generate invoices, reports, and other documents with minimal setup.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it is. breuer/laravel-pdf-chrome-driver is a driver plugin for spatie/laravel-pdf that talks to Chrome over the DevTools Protocol (CDP) directly rather than going through Browsershot → Node → Puppeteer. That is the entire value proposition: it removes the Node.js runtime and the Puppeteer dependency from the PDF rendering path while keeping the familiar Pdf::view(...)->save(...) builder API.

Architecture fit. High, in principle. spatie/laravel-pdf is explicitly driver-oriented, so this slots in as a config-level swap (config/laravel-pdf.php → driver class) without touching application call sites. It respects Laravel conventions (service provider, publishable config, container bindings), which means the blast radius of adoption is one config file plus image changes. That is the ideal shape for a contained technical bet.

Integration feasibility. Straightforward mechanically — composer require, publish config, set driver, ensure a Chrome/Chromium binary is reachable. The real work is not installation, it is behavioral equivalence with the Browsershot baseline. Browsershot encodes years of accumulated pragmatism: wait-until-network-idle, waitForFunction, delay, custom user agent, cookies, auth headers, tag-based PDF options, header/footer templates, and a dozen paper/margin knobs. A direct CDP implementation has to re-earn each of those. Every PdfBuilder method our templates use must be verified against this driver, not assumed.

What v2.0.2 changes. This is a patch release with one fix, but it is a diagnostically useful one. Inline @font-face declarations using data: URIs were not applied during rendering; the driver now waits for the page load event after Page.setDocumentContent before invoking Page.printToPDF, so Chrome has fully parsed embedded resources. Three takeaways for the assessment:

  1. A parity gap closed. Font embedding / base64 webfonts was on our list of "usual casualties" for CDP reimplementations. It is now explicitly addressed, which narrows the remaining gap set.
  2. It confirms the maturity concern was correctly framed. The failure mode here was silent degradation — PDFs rendered with fallback fonts rather than erroring. That is exactly the class of failure flagged as hardest to catch (output still looks plausible), and it appeared in a 2.0.x patch line. Assume more of these exist undiscovered.
  3. Partial answer to a key question. The driver does implement post-content-injection lifecycle waiting (at least the load event). It does not follow that network-idle, selector-based, or JS-flag waits are at parity. Question 6 below is narrowed, not closed.

Technical risk.

Risk Severity Note
Maturity / adoption High Low stars, no dependents. Effectively unproven in production by anyone but the author. Active patch cadence (2.0.1 → 2.0.2) is a modest positive signal.
Bus factor High Single maintainer, no downstream community to absorb abandonment.
CDP drift Medium Page.printToPDF is one of the more stable CDP domains, but flags and lifecycle semantics change across Chrome majors.
Feature parity gaps Medium–High Font embedding (inline/base64 @font-face) resolved in v2.0.2. Header/footer HTML, background printing, tagged/accessible PDF, and scale remain unverified.
Silent-degradation regressions Medium–High v2.0.2 is a concrete instance: fonts silently fell back. The driver's failure mode is plausible-looking wrong output, not a hard error.
Chrome lifecycle Medium Spawn-per-render vs. long-lived browser; orphan processes and memory growth are the classic failure modes.

MIT license is a meaningful mitigant: the driver surface is small and forkable, so abandonment is recoverable at modest cost.

Key questions to put to the maintainer (or answer in a spike).

  1. Which spatie/laravel-pdf major versions and PHP versions are supported, and is the driver contract stable across them?
  2. Which PdfBuilder options are honored vs. silently ignored? Is there a parity matrix against Browsershot? A published list of known-incomplete options would materially de-risk adoption.
  3. Local Chrome binary, spawned browser, or remote CDP endpoint (e.g. browserless)? Is TLS/auth supported for remote?
  4. Concurrency model: one browser per request, or a pooled/context-per-render model? What are the tested limits?
  5. Chrome version floor/ceiling, and is it exercised in CI?
  6. Narrowed: page-load-event waiting after setDocumentContent is confirmed as of v2.0.2. Still open: network-idle, selector-based waits, JS-flag waits, explicit delay, and timeout configuration.
  7. Docker/Alpine/ARM support, and --no-sandbox guidance for root containers?
  8. New: does any CI job assert on rendered output (font applied, images embedded), or only that a PDF is produced? The v2.0.2 bug would pass a "does it 200" test.

Integration Approach

Stack fit. Strong for Laravel 10–12 / PHP 8.1+ shops already on spatie/laravel-pdf. The strongest fit is containerized deployments where removing Node shrinks the image, cuts cold-start time, and eliminates a second runtime from the CVE surface — Alpine/slim images, ECS/Fargate, and any environment where a Node toolchain is otherwise carried purely for PDFs.

Migration path.

  1. Spike (1 sprint, timeboxed). Branch install, render three real templates, compare against production output.
  2. Fixture corpus. Capture the PDFs our app actually generates today — invoices, statements, reports, any with headers/footers, custom fonts, or embedded images. Explicitly include at least one template using inline base64 @font-face, since that path was broken until v2.0.2 and is the most likely place for residual font-handling defects.
  3. Diff harness. Byte-hash comparison is noisy; use page-count + visual/pixel diff plus text extraction. Gate on "no visible regression," not "identical bytes." Pixel diff is the only thing that catches a font-fallback regression.
  4. Dual-driver config. Make the driver env-selectable so rollback is a config change, not a deploy.
  5. Staging parallel run. Render both drivers for the same inputs, log divergence.
  6. Canary 5% → 50% → 100%, watching render latency and failure rate.
  7. Decommission Node from the runtime image only after full cutover.

Compatibility. Pin the package and pin Chrome (base image digest). Never let chrome:latest float — a Chrome major bump is the single most likely way this breaks in production. Floor the package constraint at ^2.0.2 if any template relies on inline fonts; 2.0.0/2.0.1 will silently produce fallback-font PDFs. Add a CI job that renders the fixture corpus on every dependency update.

Sequencing. Do this behind product work, not in front of it. There is no user-visible feature payoff — it is a cost/operability play. If the team is mid-roadmap, schedule it as a platform-hygiene item, not a committed deliverable.

Operational Impact

Maintenance. The package is small; the ownership burden is not zero. Assume we vendor or fork it within 12 months. Budget roughly 0.1–0.2 FTE for stewardship: dependency bumps, Chrome-major triage, and patching parity gaps. v2.0.2 is a fair example of the workload — a font-rendering defect in a 2.0.x line, found by the author, fixed in a patch. If we had been live on 2.0.1, our customers would have received invoices in the wrong typeface with no error anywhere. That is the shape of the ongoing cost: not outages, quiet output defects.

Support. Treat external support as nonexistent. Internal runbook required before go-live: how to reproduce a bad PDF, how to inspect Chrome stderr, how to force a driver rollback, and how to verify a font actually rendered.

Scaling. Direct CDP is the right shape for scale — one fewer process layer per render than Node+Puppeteer, lower resident memory, faster cold start. Throughput is bounded by Chrome instances, not by PHP workers. Expect ~150–300 MB per Chrome process; at meaningful volume (~10k PDFs/day) plan for a dedicated render pool or remote CDP endpoint rather than browser-per-request, and cap concurrency explicitly. Horizontal scaling is clean and stateless.

Failure modes to instrument from day one.

  • Orphaned/zombie Chrome processes in long-lived containers — the top cause of "it worked yesterday."
  • WebSocket timeouts and silent retries producing truncated or blank pages.
  • Incomplete renders from missing wait-for-idle semantics (partial fonts/images) — the v2.0.2 bug class. Reduced but not eliminated.
  • Font fallback: output renders successfully with the wrong typeface. Detect by asserting on font names in extracted text / PDF metadata, or by pixel-diffing against a known-good baseline.
  • Chrome crash under memory pressure — surfaces as a 500, not a degraded PDF.
  • --no-sandbox requirements in root containers; sandbox misconfiguration on hardened runtimes.
  • Silent option drops (a margin or header quietly ignored) — the worst class of failure because output still looks plausible.

Alert on PDF failure rate and on render duration p95 and page-count distribution; a shift in page count distribution is the earliest signal that options are being ignored. Add an output-fidelity check (font-name or pixel-baseline assertion on a sampled render) — error-rate monitoring alone would not have caught v2.0.2.

Ramp-up. Low for PHP developers — the Laravel-facing API is unchanged. New concepts are confined to CDP and Chrome operations: targets, sessions, the Page domain, browser lifecycle, and container sandboxing. Expect 1–2 days for a mid-level developer to be productive and about a week of team knowledge to own the pipeline confidently, most of it spent on the diff harness and failure-mode runbook rather than the package itself.

Overall. Architecturally correct, strategically attractive (drops Node), commercially immature. v2.0.2 is mildly reassuring — active maintenance, a real parity gap closed — but it simultaneously demonstrates that defects in this package surface as silently wrong PDFs rather than errors, which raises the value of the diff harness relative to the code change itself. Recommendation unchanged: pilot, don't standardize. Run the spike against a real fixture corpus including inline-font templates; adopt only if parity is demonstrable and someone is named as owner. The MIT license and small surface make the downside bounded — this is a cheap experiment with a real operational payoff, not a platform commitment.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel