jjalvarezl/pdfjs-viewer-bundle
A Symfony bundle that integrates Mozilla PDF.js to embed and display PDF documents in your application. It provides a ready-to-use viewer, simple configuration, and a clean way to serve PDFs without browser plugins.
Architecture fit. Unchanged in substance, and now confirmed at an older baseline. This is a Symfony bundle — Bundle subclass, DependencyInjection extension, service definitions, Twig templates — and v3.0.0 declares it stable for Symfony 3, not Symfony 4. Laravel's container, router, and Blade engine understand none of it. The only genuinely portable component remains the vendored PDF.js viewer assets plus a route that renders them against a configurable file path — roughly a Blade view, a route entry, a config array, and a public/vendor/pdfjs directory. The bundle wrapper is Symfony-shaped ceremony around a framework-agnostic JavaScript library, and the new release is purely a declaration about that ceremony.
Integration feasibility. Low, and lower than previously assessed. The prior evaluation assumed a Symfony 4 baseline; v3.0.0 confirms Symfony 3, which reached end of life in November 2018. That shifts the dependency picture from "transitive dead weight" to "hard Composer conflict": Symfony 3 component constraints (^3.0 on framework-bundle, twig-bundle, etc.) cannot co-resolve with a Laravel 10/11 application, which pins symfony/console, symfony/http-foundation, and siblings to ^6.x/^7.x. The failure is a component-level conflict, not merely a PHP floor mismatch, so composer require fails at resolution rather than at runtime. There is still no ServiceProvider and no auto-discovery. The viable path is unchanged — read the source, copy the PDF.js build/ and web/ assets into public/, reimplement the viewer route and config in Laravel, discard the bundle. That is a fork, not an integration, and should be staffed and estimated as such.
Technical risk. Still the dominant concern, and the release note does nothing to reduce it. The note contains no mention of a PDF.js version bump, no security advisory, no feature work, and no dependency refresh — it is a framework-compatibility statement and nothing more. Two axes:
isEvalSupported is left at its default. For any product where users upload or receive third-party PDFs, this is a stored-XSS-to-RCE class defect with public exploit details. A pre-2.0 viewer also predates years of rendering, worker, and font-handling fixes.The one new signal the release carries is itself negative: the maintainer's only recent act is to declare stability against a framework that died in 2018, without touching the third-party library that actually matters. That is a reasonably strong indicator of remaining maintenance capacity.
Key questions. Which exact PDF.js version is vendored — the Symfony 3 datapoint suggests 1.x, and we should confirm rather than infer? Can the viewer assets be swapped independently of the bundle, or does the Twig template hard-code asset paths? Is the viewer asset-served locally or CDN-referenced (CDN would at least allow a version bump without touching PHP)? Does isEvalSupported appear anywhere in the shipped viewer config? Does the Twig template do anything non-trivial — toolbar customization, signed-URL injection, page-range restriction — that we would reimplement in Blade? And is the requirement merely "display a PDF inline," in which case the browser's native viewer in an <iframe> or a pdfjs-dist npm dependency under Vite dominates this package on every axis?
Stack fit. Poor for Laravel, and marginal even for contemporary Symfony — v3.0.0 targets Symfony 3, two majors behind current. Treat the repository as a reference implementation and asset archive, not a library. The correct backlog framing remains "vendor PDF.js and build a thin Laravel viewer," with this repo as one input among several.
Migration path. Unchanged ranking, with the extract-and-upgrade option further deprioritized by the confirmed Symfony 3 baseline:
pdfjs-dist via npm + Vite. Install the current release, copy the viewer build in the Vite config, expose a route returning the viewer HTML with a signed file URL. Maintained, patched, idiomatic for a modern Laravel front end. Recommended.<iframe src="{signedUrl}#toolbar=0"> or a Content-Disposition: inline response costs nothing and inherits browser security patching. Choose this unless text selection, custom chrome, or page-level control are hard requirements.Compatibility. Apache-2.0 on the bundle is permissive and compatible with PDF.js's own Apache-2.0, so licensing is not a blocker — but the license covers code tied to a Symfony major that has been unsupported since November 2018. No PHP 8.2/8.3 declaration exists; composer require against Laravel 11 fails on both the PHP floor and the symfony/* major-version conflict. The v3.0.0 tag is itself a major version bump, which under semver signals breaking change relative to 2.x — irrelevant to us since we are not a dependent, but it means there is no upgrade path for anyone already on the bundle and no incentive for the author to publish a security patch to an older line.
Sequencing. (a) Timeboxed spike, half a day, to enumerate the vendored PDF.js version and diff the viewer config against stock — the Symfony 3 datapoint makes a 1.x finding the prior, so scope the spike to confirm and quantify. (b) Security review against CVE-2024-4367 and other advisories in that PDF.js range; treat a hit as a release blocker, not a backlog item. (c) Decide build-versus-extract at the spike's exit, with a default bias toward option 1. (d) If extraction wins, schedule the asset copy and Blade view as one ticket and the PDF.js upgrade as a mandatory companion ticket. (e) Nothing lands behind other feature work — it is a small, self-contained, low-coupling decision that gets more expensive as the viewer surface grows. Close out the evaluation after (c); further releases of this package should not trigger re-review unless the release notes name a PDF.js version.
Maintenance. Effectively unmaintained upstream, and v3.0.0 slightly weakens even that read: the sole recorded activity since the 2018 snapshot is a framework-stability declaration for a framework that had already reached end of life, with no dependency or security refresh. Zero commit velocity on the library that actually ships to users. Adopting it means the fork becomes ours — patching, PDF.js upgrades, browser-compatibility fixes as Chrome, Safari, and Firefox evolve canvas and worker behavior. Budget a recurring line item, small but permanent, and assign a named owner; unowned forks rot silently until a CVE lands.
Support. None. Ten stars, zero dependents, one author, no issue triage, no Stack Overflow corpus, no third-party fixes to borrow. Any defect is first-principles debugging against a Symfony bundle we have already discarded plus a JavaScript library whose version we did not choose. The new release does not change this — it adds a tag, not a support surface. Compare pdfjs-dist, where Mozilla and a very large dependent population absorb most issues.
Scaling. The one dimension where this remains benign. The viewer is static client-side JavaScript; serving it from a CDN or public/ adds no application-server load, and PDF rendering happens in the browser rather than in PHP workers. Concerns are bandwidth on large documents and client memory on 500+ page files, both of which apply equally to any PDF.js deployment and are addressable with range requests and a signed-URL file endpoint.
Failure modes. (1) A malicious or malformed PDF triggers the isEvalSupported arbitrary-JS path — highest severity, highest likelihood, mitigated only by upgrading PDF.js or setting the flag false; the 3.0.0 release provides no mitigation. (2) Broken rendering on newer browser engines as canvas and worker APIs shift under a 1.x build, presenting as intermittent customer-visible defects with no upstream fix and no realistic path to one. (3) Asset path collisions or stale cached bundles under Laravel's public/ directory, producing white-screen viewers that are tedious to diagnose. (4) Silent abandonment — the package simply stops being touched, and the next engineer discovers the age of the vendored PDF.js during an incident rather than during review. (5) A false signal from the version number: someone scanning Packagist sees a fresh 3.0.0 and concludes the package is actively maintained, which it is not.
Ramp-up. Trivial for the extraction path: an engineer fluent in Laravel routes and Blade produces a working viewer in under a day, and the conceptual surface is one JavaScript library with excellent public documentation — with the caveat that upgrading a 1.x asset set to current is a longer job than the glue code itself. The deceptive cost remains the alternative path: keeping the Symfony bundle functional inside a Laravel app now has an unbounded ramp-up and a hard Composer conflict, with no payoff, since every hour bridging containers is an hour not spent on a maintained solution. Steer decisively toward the fork; do not let the "stable release" language or the 3.0.0 version number invite an integration attempt.
How can I help you explore Laravel packages today?