Salta ai contenuti
getnextpdf.com

Perché il tuo motore PDF appartiene a PHP, non a un sidecar

Spec: ISO/IEC 25010:2023, §3.7Spec: ISO 32000-2, §7

Ci sono due posti in cui un PDF può essere fatto: dentro il tuo processo PHP, o da qualche altra parte che devi gestire. NextPDF lo fa dentro. Questa pagina è l’argomentazione a favore di quella scelta — perché un motore in-process è di solito il giusto default, e cosa costi davvero il modello «da qualche altra parte» una volta in produzione.

Questo è l’angolo architetturale, non quello del framework. Come lo stesso motore raggiunga Laravel, Symfony, CodeIgniter e codice autonomo è un’altra storia, raccontata in one engine, every framework.

Una funzionalità PDF raramente nasce come un sistema da gestire. Nasce come una riga in un controller: renderizza questa fattura, restituisci quel report. Il modello sidecar trasforma quella riga in infrastruttura. Per disegnare il documento ora fai girare una seconda cosa — un binario esterno, un browser headless, un microservizio separato — e tutto ciò di cui quella seconda cosa ha bisogno diventa un tuo problema anche: la sua versione, la sua memoria, il suo container, la sua rete, le sue modalità di guasto, la sua chiamata di reperibilità alle 2 di notte.

Il costo è invisibile nella demo e inevitabile in produzione. Un motore documentale che vive nel tuo processo non ne ha nessuno. La domanda non è «può un sidecar fare un PDF» — certo che può. È «cosa hai accettato di gestire per arrivarci, e ne avevi bisogno».

  • In-process significa nessun secondo runtime. NextPDF disegna il PDF dentro lo stesso worker PHP che ha gestito la richiesta. Non c’è alcun sottoprocesso da generare, nessun servizio da distribuire e nulla di extra da tenere in vita.
  • Un sidecar aggiunge una superficie operativa che non avevi. Un browser incluso o un binario esterno porta con sé la propria versione, la propria impronta di sicurezza e il proprio container — tutte cose che ora patchi e monitori.
  • I confini di processo sono dove le cose vanno storte. Cold start, timeout, fragile idraulica tra processi e dati che lasciano il tuo processo sono modalità di guasto che una chiamata in-process semplicemente non ha.
  • In-process è testabile e deterministico. Il motore è PHP tipizzato che puoi sottoporre a unit test, mockare e su cui puoi ragionare — non un renderer opaco che puoi sondare solo eseguendolo e guardando l’output.
  • Un vero browser ha comunque usi reali. Per il rendering fedele al pixel di pagine web moderne arbitrarie, un browser headless è lo strumento onesto — e NextPDF può delegare a uno deliberatamente. È un punto di giunzione, non il default.

Tieni le due architetture l’una accanto all’altra. Il percorso in-process è una chiamata di funzione. Il percorso sidecar è un sistema distribuito in miniatura — e ogni freccia tra le sue scatole è un punto che fallisce indipendentemente dal tuo codice.

  1. In-process: chiama il motorewriteHtml() o l'API documentale gira dentro il worker PHP corrente — nessun sottoprocesso, nessun socket.
  2. In-process: ricevi i byte del PDFIl motore restituisce direttamente contenuto PDF nativo; nulla ha lasciato il processo.
  3. Sidecar: serializza e spedisciMarkup o una richiesta vengono marshallati fuori dal tuo processo verso un binario, un browser o un servizio remoto.
  4. Sidecar: attraversa il confineUna generazione di processo o un salto di rete — con un cold start, un timeout e un contratto IPC che può rompersi.
  5. Sidecar: fai girare un secondo runtimeUn renderer esterno con la propria versione, profilo di memoria e superficie di sicurezza da gestire e patchare.
  6. Sidecar: deserializza di ritornoMarshalla indietro il risultato e traduci gli errori del renderer nei tuoi.
Il percorso in-process contro il percorso sidecar. In-process, il PDF è prodotto da una chiamata tipizzata dentro lo stesso worker PHP e restituito direttamente. Il percorso sidecar aggiunge un passo di serializzazione, un confine di processo o di rete, un runtime esterno con la propria versione e impronta, e un passo di deserializzazione di ritorno — ciascuno una distinta modalità di guasto che la chiamata in-process non ha.

Nessun secondo runtime da gestire. Il modello sidecar è due sistemi che indossano il costume di una sola funzionalità. Un wkhtmltopdf incluso, un servizio Chromium headless, un microservizio di rendering separato — ognuno è un runtime con la propria cadenza di rilascio e i propri bug. Li erediti tutti. Il motore in-process viene spedito come dipendenza Composer; viene aggiornato come ogni altra libreria nel tuo composer.json, senza alcun demone, immagine o socket aggiunto alla tua distribuzione.

Deriva di versione e una superficie di sicurezza più ampia. Un browser incluso è una codebase grande e in rapido movimento con un flusso costante di avvisi di sicurezza. Bloccalo e marcisce; seguilo e cambia di continuo. In entrambi i casi è l’intera piattaforma web di un renderer seduta nella tua supply chain per alimentare un documento. Un motore PHP in-process è una libreria di codice focalizzata che puoi leggere; la sua superficie di sicurezza è il PHP che già fai girare, non una seconda piattaforma che ora fai girare anche.

I dati restano dentro il confine del tuo processo. Quando deleghi a un processo esterno, il contenuto del documento — che spesso è esattamente il dato sensibile per portare il quale un PDF esiste — attraversa un confine. Viene scritto su una pipe, un argomento, un file temporaneo o un socket di rete verso un servizio. Ognuno di questi è un punto da cui far trapelare, in cui loggare per sbaglio o che lasciare dietro di sé. In-process, il dato non lascia mai il worker che lo possiede. Il raggio dell’esplosione è un processo, non una flotta.

Idraulica fragile, cold start e timeout. Le chiamate tra processi e di rete falliscono in modi che una chiamata di funzione non può: il sottoprocesso che non si è avviato, il socket che si è bloccato, il timeout che hai indovinato male, il cold start sotto un picco di traffico. Ognuno ha bisogno di una politica di retry, di un circuit breaker e di un budget. Un render in-process o restituisce byte o lancia un’eccezione tipizzata che catturi alla riga successiva. Non c’è alcuno stato di rete parziale da riconciliare.

Osservabilità e testing diventano più difficili attraverso il confine. Un guasto in un sidecar arriva come un exit code, una riga di log troncata o un 500 da un servizio che non controlli. Riprodurlo significa riprodurre tutto quell’ambiente. Un motore in-process è osservabile con gli strumenti che già usi — uno stack trace, un debugger, un profiler — ed è testabile come il resto del tuo PHP. Quella testabilità è una proprietà nominata di qualità del software: ISO/IEC 25010 la colloca sotto manutenibilità (Spec: ISO/IEC 25010:2023, §3.7), e una libreria in-process la soddisfa molto più direttamente di un renderer che puoi esercitare solo lanciandolo.

Il PDF su cui quei test fanno asserzioni è una struttura definita, non una scatola nera. Un file PDF ha una disposizione di oggetti e di file specificata (Spec: ISO 32000-2, §7), e un motore in-process emette quella struttura da codice che puoi leggere — così che un golden-file o un test strutturale verifichi byte che una funzione nota ha prodotto, anziché l’output di un programma esterno che puoi solo osservare.

Tutto il punto sta in una manciata di righe. Non c’è alcun client, nessun base URL, nessun health check e nessuna politica di retry — perché non c’è alcun secondo sistema.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// The engine runs inside this very process. No subprocess is spawned,
// no socket is opened, and the report data never leaves the worker.
$document = Document::createStandalone();
$document->setTitle('Quarterly Report');
$document->addPage();
$html = <<<'HTML'
<h1 style="color: #1E3A8A;">Quarterly Report</h1>
<p>Rendered <strong>in-process</strong> by PHP — no browser, no sidecar.</p>
HTML;
$document->writeHtml($html);
// PDF bytes are returned directly. There is no boundary to marshal across,
// so there is no timeout, cold start, or deserialization step to handle.
$bytes = $document->getPdfData();

Confronta la forma della versione sidecar — non il suo codice, la sua forma operativa. Ha bisogno che un binario o un servizio sia installato e raggiungibile, di una richiesta serializzata e inviata, di un timeout scelto, di un percorso di guasto per quando il renderer è freddo o giù, e del risultato marshallato indietro. Niente di tutto ciò è nello snippet qui sopra, perché niente di tutto ciò esiste quando il motore è una libreria.

Il presupposto frequente è che il «vero» rendering PDF debba significare un browser, quindi l’in-process dev’essere la versione giocattolo. Questo ha il compromesso al contrario. Un browser è lo strumento giusto quando hai bisogno di un rendering esatto e fedele al pixel di contenuto web moderno arbitrario. È il default sbagliato per il lavoro a forma di documento che la maggior parte dei team fa davvero — fatture, report, estratti conto, contratti — dove il layout è noto, i dati sono tuoi e la correttezza è verificata da un validatore, non a occhio. Per quel lavoro, il peso operativo di un sidecar non ti compra nulla che il motore in-process non dia già, e ti costa tutto nelle sezioni qui sopra.

L’equivoco speculare è quello che questa pagina sta attenta a non commettere: affermare che un motore in-process renderizzi «tutto il web» come un browser. Non lo fa, e NextPDF non finge che lo faccia. Il suo pipeline HTML in-process è un sottoinsieme allineato alle specifiche focalizzato sul layout documentale, con confini documentati — l’ambito onesto è esposto in the HTML pipeline. Quando hai genuinamente bisogno di piena fedeltà del browser, quella è una delega deliberata e opt-in, non un ripiego silenzioso.

In-process è il giusto default. Non è un’affermazione universale secondo cui un sottoprocesso non è mai giustificato. Dove un documento richiede genuinamente il rendering esatto di CSS moderno arbitrario che il motore in-process non copre, delegare a un browser headless è la scelta corretta — e NextPDF supporta quel percorso deliberatamente, con il suo accesso alla rete vincolato, come punto di giunzione anziché come default. I due non sono rivali; sono strumenti diversi per lavori diversi.

Questa pagina argomenta l’architettura, non una matrice di supporto CSS. Esattamente quale HTML e CSS il pipeline in-process copra è definito dal codice del motore e dai suoi test di conformità, ed è documentato con quel pipeline — non promesso qui. «In-process» descrive il percorso di rendering predefinito; non è un’affermazione che ogni percorso possibile eviti un sottoprocesso.

La superficie delle capacità resta semplice: il motore in-process è Core, e il percorso di delega al browser è un’estensione opzionale, indipendente dall’edizione.

Where the PDF is rendered — edition availability
EditionAvailability
CoreCore renderizza il PDF in-process in PHP — nessun sottoprocesso, binario o sidecar per impostazione predefinita.
ProIl percorso di delega al browser headless è un’estensione add-on opzionale, indipendente dal livello di edizione.
EnterpriseIl percorso di delega al browser headless è un’estensione add-on opzionale, indipendente dal livello di edizione.
  • The HTML pipeline — l’ambito onesto del motore in-process, ed esattamente quando delegare a un browser è giusto.
  • One engine, every framework — l’asse complementare: come lo stesso motore in-process raggiunge ogni framework PHP senza una libreria diversa per stack.
  • Operating NextPDF in production — com’è far girare un motore in-process giorno per giorno, senza alcun runtime extra da gestire.
  • Memory and streaming — come il motore mantiene limitata la generazione in-process sotto carico.
  • Generazione in-process — produrre il PDF dentro lo stesso worker PHP che gestisce la richiesta, senza alcun sottoprocesso, socket o servizio esterno.
  • Sidecar — un runtime separato che gira accanto alla tua applicazione per fare un lavoro; qui, un binario esterno, un browser headless o un microservizio che renderizza il PDF fuori dal tuo processo.
  • Cold start — la latenza e il picco di risorse incorsi quando un sottoprocesso o un servizio deve essere avviato da zero prima di poter servire la prima richiesta.
  • IPC — comunicazione tra processi: le pipe, i socket, i file temporanei o le chiamate di rete usate per passare dati a e da un processo separato, e una fonte ricorrente di guasti fragili e difficili da debuggare.
  • Punto di giunzione di delega al browser — il percorso opzionale e opt-in che consegna un render a un browser headless per fedeltà esatta, con l’accesso di rete alle sottorisorse bloccato; una scelta deliberata, non il default.