Zum Inhalt springen

NextPDF Artisan – Überblick

NextPDF Artisan ist die Chrome-Brücke für NextPDF. Sie sendet ein HTML-Fragment über das Chrome DevTools Protocol an einen Headless-Chrome-Prozess, fängt die Ausgabe von printToPDF ab und bettet das Ergebnis als Form XObject in das Zieldokument ein. Der eingebettete Text bleibt auswählbar und durchsuchbar.

Das Artisan-Paket (nextpdf/artisan) erweitert die quelloffene NextPDF-Engine um einen Renderer, der das Layout an Chrome delegiert. Die native HTML-Pipeline von NextPDF deckt bereits eine breite CSS-Teilmenge ab. Die Artisan-Brücke ist für Dokumente vorgesehen, die ein Layout in Chrome-Qualität benötigen – CSS-Flexbox und -Grid, eigene Webfonts aus Data-URIs und komplexe Selektoren –, und erzeugt dabei weiterhin Vektortext statt eines gerasterten Screenshots.

Die Brücke ist eine Pipeline aus kleinen Komponenten mit jeweils klar abgegrenzter Verantwortung. ChromeHtmlRenderer orchestriert einen Render-Vorgang. ChromeSecurityPolicy validiert die Eingabe und verpackt sie in ein isoliertes HTML-Dokument. BrowserPool verwaltet den Lebenszyklus des Chrome-Prozesses. ViewportCalculator bildet PDF-Punkte auf CSS-Pixel ab. Der NextPDF\Parser-Reader parst die Chrome-Ausgabe, und PageImporter wandelt sie in ein Form XObject um. Jede Komponente ist final, wird über den Konstruktor injiziert und ist auf PHPStan-Level 10 typisiert.

Die Brücke ist an eine externe Abhängigkeit gebunden. Sie benötigt die Bibliothek chrome-php/chrome (^1.15) sowie eine Chrome- oder Chromium-Binärdatei, die der PHP-Prozess erreichen kann. Beides wird nicht mitgeliefert. Fehlt die Bibliothek, löst die Brücke ChromeNotAvailableException aus, statt stillschweigend auf einen minderwertigen Pfad auszuweichen – siehe /integrations/artisan/failure-modes/ auf der Seite /integrations/artisan/troubleshooting/.

Ein Render-Vorgang erreicht Chrome nie, bevor die Eingabe ChromeSecurityPolicy::validate() durchlaufen hat. Das Dokument, das Chrome erhält, ist außerdem immer mit einer strikten Content-Security-Policy und einer CDP-Netzwerksperre nach dem Defense-in-Depth-Prinzip umhüllt. Weil die Brücke potenziell nicht vertrauenswürdiges HTML verarbeitet, ist ihr Transport- und Isolationsmodell ausdrücklich auf der Seite /integrations/artisan/security-and-operations/ dokumentiert, statt hier zusammengefasst zu werden.

Dies ist das beobachtete Verhalten des Pakets im Auslieferungszustand, verifiziert anhand von src/Artisan/ und der Suite tests/Unit/Artisan/. Damit wird keine pixelgenaue Übereinstimmung mit einem interaktiven Chrome-Browser behauptet: Animationen werden in ihrem letzten Frame erfasst, das Layout verlässt sich nicht auf JavaScript, und nur die erste Chrome-Seite wird importiert.

HTML fragment

ChromeSecurityPolicy::validate()

ChromeSecurityPolicy::wrapHtml()

CSP + reset CSS

BrowserPool

headless Chrome

CDP: Network.setBlockedURLs '*'

Page.setDocumentContent

Chrome printToPDF

NextPDF\\Parser\\PdfReader

PageImporter → Form XObject

Embedded in target PDF

(text selectable)

Diagram
KomponenteVerantwortlichkeitQuelle
ChromeHtmlRendererOrchestriert einen einzelnen Render-Vorgang; liefert ChromeRenderResultsrc/Artisan/ChromeHtmlRenderer.php
ChromeRendererConfigUnveränderliches Konfigurationswertobjektsrc/Artisan/ChromeRendererConfig.php
ChromeSecurityPolicyEingabevalidierung + sichere HTML-Hüllesrc/Artisan/ChromeSecurityPolicy.php
BrowserPoolLebenszyklus des Chrome-Prozesses und Neustartrichtliniesrc/Artisan/BrowserPool.php
ViewportCalculatorUmrechnung 72 pt/inch ↔ 96 px/inchsrc/Artisan/ViewportCalculator.php
ChromeRenderResultTypisierte Render-Ausgabe (ChromeRenderResultInterface)src/Artisan/ChromeRenderResult.php
PageImporterGeparste Chrome-Seite → ImportedFormXObjectsrc/Artisan/PageImporter.php
EInvoiceServiceFactoryContainerfreie Factory für Premium-E-Invoice-Verträgesrc/Artisan/EInvoiceServiceFactory.php
  • Versionsherkunft. Das veröffentlichte Composer-Artefakt ist mit v0.1.0 getaggt. Docblocks im Quellcode tragen @since 1.7.0 (Chrome-Brücke) und @since 1.1.0 (E-Invoice-Factory), beide geerbt aus dem Versionsstrang von nextpdf/core vor der Umbenennung; das Paket wurde im Rahmen des CHANGELOG-Eintrags 2.0.0 in nextpdf/artisan umbenannt. Behandeln Sie den Composer-Tag als die maßgebliche Installationsversion und die @since-Marker als Herkunftsnachweis der Engine-Version.
  • Nur die erste Seite. PageImporter::import() verwendet standardmäßig den Seitenindex 0. Inhalt, der auf eine zweite Chrome-Seite überläuft, wird abgeschnitten, sofern keine explizite Höhe angegeben ist – dies wird auf der Seite /integrations/artisan/production-usage/ behandelt.
  • Kein DI-Container. Artisan arbeitet ohne Container. EInvoiceServiceFactory stellt Umgebungen ohne Service-Container eine konsistente Instanziierungsoberfläche bereit; siehe /integrations/artisan/boot-and-discovery/.

Jeder Render-Vorgang trägt den Aufwand für das Laden der Chrome-Seite und printToPDF einmal pro Aufruf. BrowserPool hält den Chrome-Prozess zwischen Render-Vorgängen am Leben und startet ihn alle 100 Render-Vorgänge neu, um das Speicherwachstum zu begrenzen. Für die Big-O-Betrachtung ist das Layout der Eingabe durch Chrome maßgeblich, nicht die Brücke selbst. Das gemessene Budget für den Referenzablauf dieser Seite finden Sie unter performance_budget im Front-Matter und auf der Seite /integrations/artisan/production-usage/.

Die Brücke rendert potenziell nicht vertrauenswürdiges HTML in Chrome. Die Eingabe wird größen- und inhaltsvalidiert, bevor Chrome sie erhält. Das umhüllte Dokument trägt default-src 'none'. Eine Sperre auf CDP-Ebene stoppt jede Subressourcenanfrage. Das vollständige Transport- und Isolationsmodell – einschließlich der ausdrücklichen Grenzen des Chrome-Sandbox-Flags – steht auf der Seite /integrations/artisan/security-and-operations/. Betrachten Sie diesen Abschnitt nicht als die vollständige Sicherheitslage.

Die quelloffene Brücke rendert HTML zu PDF. Die Premium-Stufen setzen konformes E-Invoice-Embedding (Pro) und -Validierung (Enterprise) auf das gerenderte Dokument. Wenn diese Stufen nicht installiert sind, gibt EInvoiceServiceFactory null zurück, sodass der quelloffene Pfad auch ohne sie voll funktionsfähig bleibt.

  • /integrations/artisan/install/
  • /integrations/artisan/configuration/
  • /integrations/artisan/quickstart/
  • /integrations/artisan/chrome-renderer-setup/
  • /integrations/artisan/security-and-operations/
  • /integrations/artisan/production-usage/