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

Rasterize Bundle Laravel Package

padam87/rasterize-bundle

A Symfony bundle for converting PDFs and other documents into images. It configures rasterizer services and backends, making it easy to generate thumbnails, previews, or page images from uploaded files with minimal setup in Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to internalise: this is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/rasterize.php. It auto-configures a RasterizerInterface service through Symfony's DI container. That means you have three realistic paths into it from a Laravel codebase:

  1. Sidecar service – stand up a tiny Symfony (or plain PHP) app in Docker that exposes POST /rasterize, and call it over HTTP from Laravel. Most common and least painful.
  2. Borrow the adapters – pull the bundle in and instantiate the concrete rasterizer classes manually (they're mostly thin wrappers around a CLI process), wiring them up in a Laravel service provider yourself.
  3. Monorepo – if you already run a Symfony service, use it there and call it from Laravel.

Whichever route you take, the actual work is done by an external binary. You need one of:

  • Puppeteer – Node + puppeteer + a small render script (or puppeteer-cli). Best fidelity, current recommendation.
  • PhantomJS – deprecated, unmaintained, and a known security/compat liability. Do not start greenfield projects on this.
  • wkhtmltopdf / Chrome headless / others – whatever the bundle ships an adapter for; check src/Rasterizer/ for the exact list.

Minimal install:

composer require padam87/rasterize-bundle
# plus the binary, e.g. in the image:
# npm i -g puppeteer-cli   (or vendor a small script)

Where to look first, in this order:

  • src/RasterizerInterface.php – the contract; usually one method like rasterize(string $html, string $path): void.
  • Resources/config/ – the service definitions and tags; this tells you how to wire it without the bundle.
  • DependencyInjection/Configuration.php – the full config tree, including per-adapter options.
  • The concrete adapter you intend to use – it's where the CLI flags live.

First use case: an invoice or end-of-month report. Render a Blade view to an HTML string, hand it to the rasterizer, write the PDF to storage/app/invoices/, return a signed URL. Render first, rasterize second — never ask the rasterizer to fetch your app's HTML over HTTP unless you control auth and timing.

Implementation Patterns

Inject and call, don't instantiate. In Symfony you'd type-hint RasterizerInterface; in Laravel, bind the concrete adapter in a service provider and inject it into a small PdfGenerator service of your own:

$this->app->bind(RasterizerInterface::class, fn () => new PuppeteerRasterizer(
    binary: config('services.rasterize.puppeteer_bin'),
    options: config('services.rasterize.options'),
));

Wrap it — a one-method PdfGenerator interface — so you can swap backend or fake it in tests without touching call sites.

Chain / registry pattern. The bundle's value proposition is that multiple rasterizers coexist. Use it: Puppeteer for anything with JS or modern CSS, wkhtmltopdf as the fast path for simple static HTML, and a fallback in a try/catch when the primary times out. Route by job type rather than by feature flag.

Render → rasterize, with assets made absolute. This is the pattern that saves the most debugging time. Render Blade to a string, then rewrite relative asset URLs to absolute file paths or a signed HTTP URL the headless browser can actually reach. asset() output pointing at http://localhost will 404 inside the container.

Queue it. PDF generation is seconds-long and memory-hungry. Push a GenerateInvoicePdf job, write to the local/s3 disk, notify via broadcast. Keep the HTTP path synchronous only for small single-page docs.

Config layering. Keep rasterizer choice and options in config/services.php, mirroring the bundle's config tree: default backend, per-backend timeout, viewport, format, margin, waitUntil. Read the bundle's Configuration.php and copy the shape rather than inventing keys.

Testing. Write a FakeRasterizer that writes a fixture PDF and asserts on the HTML it received — that's what you actually want to regression-test (template content, not Chromium's layout engine).

Gotchas and Tips

  • Low bus factor. 15 stars, zero dependents, a single maintainer. Pin the exact version and keep your PdfGenerator wrapper thin so you can replace the backend in an afternoon. Treat it as a reference implementation more than a load-bearing dependency.
  • PhantomJS is dead. If a tutorial or the README steers you there, ignore it. Use Puppeteer/Chromium.
  • Chromium in Docker. Expect No usable sandbox and /dev/shm crashes. Run with --no-sandbox --disable-dev-shm-usage --disable-gpu, and give the container ≥1GB RAM. Slim images also lack fonts — install fonts-liberation or you'll get tofu boxes instead of your invoice text.
  • Async rendering races. Charts and webfonts load after DOMContentLoaded. Set waitUntil: networkidle0 (or equivalent), and for JS chart libs add an explicit wait on a selector or a data-rendered flag. This is the single most common "why is my PDF blank" cause.
  • Relative paths. Headless Chrome resolves them against the document URL. A string of HTML has no base URL, so relative paths silently fail. Use <base href="..."> or absolute file:// paths.
  • Process handling. Always capture stderr and check the exit code — CLI rasterizers happily exit 0 with a truncated or empty PDF. Log the command line (redacting tokens) on failure; you'll need it.
  • Timeouts and temp files. Set a hard timeout at both the PHP and the browser level; a hung Chromium will pin a queue worker forever. Put temp HTML in storage/app/tmp and clean up in a finally.
  • Headers/footers/page numbers are backend-specific. Don't assume the same options object works across adapters; write per-adapter config and test each.
  • Extension point. If you stay in Symfony, implementing RasterizerInterface and tagging the service is the intended way to add a backend. In Laravel, that translates to a Rasterizer contract plus a driver-style resolver — mirror the bundle's naming so upstream examples stay legible.
  • Don't serve the raw CLI from web requests. If you build a sidecar, put an allowlist on what HTML can reference (no file:///etc/passwd), or you've shipped an SSRF/local-file-read gadget.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle