Przejdź do głównej zawartości
getnextpdf.com

Dlaczego twój silnik PDF należy do PHP, a nie do przyczepki

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

Są dwa miejsca, w których można utworzyć PDF: wewnątrz twojego procesu PHP albo gdzieś indziej, co musisz obsługiwać. NextPDF tworzy go wewnątrz. Ta strona to argument za tym wyborem — dlaczego silnik działający w ramach procesu jest zwykle właściwym domyślnym wyborem oraz ile wzorzec „gdzieś indziej” faktycznie kosztuje, gdy już jest na produkcji.

To ujęcie architektoniczne, a nie frameworkowe. To, jak ten sam silnik dociera do Laravela, Symfony, CodeIgnitera i samodzielnego kodu, to inna historia, opowiedziana w jeden silnik, każdy framework.

Funkcja PDF rzadko zaczyna się jako system, który obsługujesz. Zaczyna się jako linijka w kontrolerze: wyrenderuj tę fakturę, zwróć ten raport. Wzorzec przyczepki zamienia tę linijkę w infrastrukturę. Aby narysować dokument, uruchamiasz teraz drugą rzecz — zewnętrzny plik binarny, bezgłową przeglądarkę, osobny mikroserwis — a wszystko, czego ta druga rzecz potrzebuje, staje się również twoim problemem: jej wersja, jej pamięć, jej kontener, jej sieć, jej tryby awarii, jej wezwanie na dyżur o 2 w nocy.

Koszt jest niewidoczny na demie i nieunikniony na produkcji. Silnik dokumentów, który żyje w twoim procesie, nie ma żadnego z nich. Pytanie nie brzmi „czy przyczepka potrafi zrobić PDF” — oczywiście, że potrafi. Brzmi „co zobowiązałeś się obsługiwać, by tam dotrzeć, i czy musiałeś”.

  • Działanie w ramach procesu oznacza brak drugiego środowiska uruchomieniowego. NextPDF rysuje PDF wewnątrz tego samego procesu roboczego PHP, który obsłużył żądanie. Nie ma podprocesu do uruchomienia, usługi do wdrożenia ani niczego dodatkowego do utrzymywania przy życiu.
  • Przyczepka dodaje powierzchnię operacyjną, której nie miałeś. Dołączona przeglądarka lub zewnętrzny plik binarny przynosi własną wersję, własny ślad bezpieczeństwa i własny kontener — a wszystko to teraz łatasz i monitorujesz.
  • Granice procesów to miejsca, w których coś idzie nie tak. Zimne starty, przekroczenia czasu, kruche połączenia między procesami i dane opuszczające twój proces to tryby awarii, których wywołanie w ramach procesu po prostu nie ma.
  • Działanie w ramach procesu jest testowalne i deterministyczne. Silnik to typowane PHP, które możesz testować jednostkowo, mockować i o którym możesz wnioskować — a nie nieprzejrzysty mechanizm renderujący, który możesz badać jedynie przez uruchamianie go i oglądanie wyniku.
  • Prawdziwa przeglądarka wciąż ma realne zastosowania. Do wiernego co do piksela renderowania dowolnych nowoczesnych stron internetowych bezgłowa przeglądarka jest uczciwym narzędziem — a NextPDF potrafi celowo delegować do niej zadanie. To styk, a nie domyślne ustawienie.

Zestaw obie architektury obok siebie. Ścieżka w ramach procesu to wywołanie funkcji. Ścieżka przyczepki to system rozproszony w miniaturze — a każda strzałka między jego pudełkami to miejsce, które zawodzi niezależnie od twojego kodu.

  1. In-process: call the enginewriteHtml() or the document API runs inside the current PHP worker — no subprocess, no socket.
  2. In-process: receive PDF bytesThe engine returns native PDF content directly; nothing left the process.
  3. Sidecar: serialize and shipMarkup or a request is marshalled out of your process to a binary, browser, or remote service.
  4. Sidecar: cross the boundaryA process spawn or network hop — with a cold start, a timeout, and an IPC contract that can break.
  5. Sidecar: run a second runtimeAn external renderer with its own version, memory profile, and security surface to operate and patch.
  6. Sidecar: deserialize backMarshal the result back in and translate the renderer’s errors into yours.
Ścieżka w ramach procesu kontra ścieżka przyczepki. W ramach procesu PDF jest tworzony przez typowane wywołanie wewnątrz tego samego procesu roboczego PHP i zwracany bezpośrednio. Ścieżka przyczepki dodaje krok serializacji, granicę procesu lub sieci, zewnętrzne środowisko uruchomieniowe z własną wersją i śladem oraz krok deserializacji z powrotem — każdy z nich to odrębny tryb awarii, którego wywołanie w ramach procesu nie ma.

Brak drugiego środowiska uruchomieniowego do obsługi. Wzorzec przyczepki to dwa systemy w kostiumie jednej funkcji. Dołączony wkhtmltopdf, usługa bezgłowego Chromium, osobny mikroserwis renderujący — każdy jest środowiskiem uruchomieniowym z własną kadencją wydań i własnymi błędami. Dziedziczysz to wszystko. Silnik działający w ramach procesu jest dostarczany jako zależność Composer; aktualizuje się go tak, jak każdą inną bibliotekę w twoim composer.json, bez dodawania do twojego wdrożenia żadnego demona, obrazu ani gniazda.

Dryf wersji i szersza powierzchnia bezpieczeństwa. Dołączona przeglądarka to duża, szybko zmieniająca się baza kodu ze stałym strumieniem porad bezpieczeństwa. Przypnij ją, a zgnije; śledź ją, a będzie się burzyć. Tak czy inaczej, to cała platforma internetowa mechanizmu renderującego osadzona w twoim łańcuchu dostaw, by nakarmić jeden dokument. Silnik PHP działający w ramach procesu to skupiona biblioteka kodu, który możesz czytać; jego powierzchnia bezpieczeństwa to PHP, które już uruchamiasz, a nie druga platforma, którą teraz też uruchamiasz.

Dane pozostają wewnątrz granicy twojego procesu. Gdy wywołujesz na zewnątrz, treść dokumentu — która często jest dokładnie tymi wrażliwymi danymi, dla których nośnika istnieje PDF — przekracza granicę. Jest zapisywana do potoku, argumentu, pliku tymczasowego lub gniazda sieciowego do usługi. Każde z tych miejsc to miejsce wycieku, przypadkowego zalogowania lub pozostawienia. W ramach procesu dane nigdy nie opuszczają procesu roboczego, który jest ich właścicielem. Promień rażenia to jeden proces, a nie flota.

Kruche połączenia, zimne starty i przekroczenia czasu. Wywołania między procesami i sieciowe zawodzą w sposób, w jaki wywołanie funkcji nie może: podproces, który się nie uruchomił, gniazdo, które zawisło, przekroczenie czasu, które źle zgadłeś, zimny start podczas skoku ruchu. Każde wymaga polityki ponowień, bezpiecznika i budżetu. Renderowanie w ramach procesu albo zwraca bajty, albo zgłasza typowany wyjątek, który łapiesz w następnej linijce. Nie ma częściowego stanu sieciowego do uzgodnienia.

Obserwowalność i testowanie stają się trudniejsze ponad granicą. Awaria w przyczepce przychodzi jako kod wyjścia, ucięta linia logu lub błąd 500 z usługi, której nie kontrolujesz. Odtworzenie jej oznacza odtworzenie całego tego środowiska. Silnik działający w ramach procesu jest obserwowalny narzędziami, których już używasz — ślad stosu, debugger, profiler — i jest testowalny tak, jak reszta twojego PHP. Ta testowalność to nazwana właściwość jakości oprogramowania: ISO/IEC 25010 umieszcza ją pod utrzymywalnością (Spec: ISO/IEC 25010:2023, §3.7), a biblioteka działająca w ramach procesu spełnia ją znacznie bardziej bezpośrednio niż mechanizm renderujący, który możesz ćwiczyć jedynie przez jego uruchomienie.

PDF, na którym te testy formułują asercje, to zdefiniowana struktura, a nie czarna skrzynka. Plik PDF ma określony układ obiektów i pliku (Spec: ISO 32000-2, §7), a silnik działający w ramach procesu emituje tę strukturę z kodu, który możesz czytać — więc test plikiem wzorcowym lub strukturalny sprawdza bajty wyprodukowane przez znaną funkcję, a nie wynik zewnętrznego programu, który możesz jedynie obserwować.

Cała rzecz mieści się w garstce linijek. Nie ma klienta, nie ma bazowego adresu URL, nie ma kontroli stanu i nie ma polityki ponowień — bo nie ma drugiego systemu.

<?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();

Zestaw kształt wersji z przyczepką — nie jej kod, jej kształt operacyjny. Wymaga ona zainstalowania i osiągalności pliku binarnego lub usługi, żądania zserializowanego i wysłanego, wybranego przekroczenia czasu, ścieżki awarii na wypadek, gdy mechanizm renderujący jest zimny lub niedostępny, oraz wyniku zmarszalowanego z powrotem. Niczego z tego nie ma w powyższym fragmencie, bo nic z tego nie istnieje, gdy silnik jest biblioteką.

Częstym założeniem jest to, że „prawdziwe” renderowanie PDF musi oznaczać przeglądarkę, więc działanie w ramach procesu musi być wersją-zabawką. To odwraca kompromis na opak. Przeglądarka jest właściwym narzędziem, gdy potrzebujesz dokładnego, wiernego co do piksela renderowania dowolnej nowoczesnej treści internetowej. Jest złym domyślnym wyborem do pracy o kształcie dokumentu, którą większość zespołów faktycznie wykonuje — faktur, raportów, wyciągów, umów — gdzie układ jest znany, dane są twoje, a poprawność sprawdza walidator, a nie oko. Do takiej pracy operacyjny ciężar przyczepki nie kupuje ci niczego, czego silnik działający w ramach procesu już ci nie daje, a kosztuje cię wszystko z powyższych sekcji.

Lustrzanym nieporozumieniem jest to, którego ta strona starannie nie popełnia: twierdzenie, że silnik działający w ramach procesu renderuje „całą sieć” jak przeglądarka. Nie renderuje i NextPDF nie udaje, że tak jest. Jego potok HTML działający w ramach procesu to zgodny ze specyfikacją podzbiór skupiony na układzie dokumentu, z udokumentowanymi granicami — uczciwy zakres jest przedstawiony w potoku HTML. Gdy naprawdę potrzebujesz pełnej wierności przeglądarki, jest to celowe, opcjonalne delegowanie, a nie ciche rozwiązanie awaryjne.

Działanie w ramach procesu jest właściwym domyślnym wyborem. Nie jest to uniwersalne twierdzenie, że podproces nigdy nie jest uzasadniony. Tam, gdzie dokument naprawdę wymaga dokładnego renderowania dowolnego nowoczesnego CSS, którego silnik działający w ramach procesu nie obejmuje, delegowanie do bezgłowej przeglądarki jest poprawnym wyborem — a NextPDF celowo wspiera tę ścieżkę, z ograniczonym dostępem sieciowym, jako styk, a nie domyślne ustawienie. Te dwa nie są rywalami; to różne narzędzia do różnych zadań.

Ta strona argumentuje za architekturą, a nie za macierzą obsługi CSS. To, który dokładnie HTML i CSS obejmuje potok działający w ramach procesu, jest określone przez kod silnika i jego testy zgodności i jest udokumentowane razem z tym potokiem — a nie obiecywane tutaj. „W ramach procesu” opisuje domyślną ścieżkę renderowania; nie jest to twierdzenie, że każda możliwa ścieżka unika podprocesu.

Powierzchnia możliwości pozostaje prosta: silnik działający w ramach procesu jest częścią Core, a ścieżka delegowania do przeglądarki jest opcjonalnym rozszerzeniem, niezależnym od edycji.

Where the PDF is rendered — edition availability
EditionAvailability
CoreCore renderuje PDF w ramach procesu w PHP — domyślnie bez podprocesu, pliku binarnego ani przyczepki.
ProŚcieżka delegowania do bezgłowej przeglądarki to opcjonalne rozszerzenie dodatkowe, niezależne od poziomu edycji.
EnterpriseŚcieżka delegowania do bezgłowej przeglądarki to opcjonalne rozszerzenie dodatkowe, niezależne od poziomu edycji.
  • Potok HTML — uczciwy zakres silnika działającego w ramach procesu oraz dokładnie wtedy, gdy delegowanie do przeglądarki jest słuszne.
  • Jeden silnik, każdy framework — oś komplementarna: jak ten sam silnik działający w ramach procesu dociera do każdego frameworka PHP bez osobnej biblioteki na stos.
  • Obsługa NextPDF na produkcji — jak wygląda na co dzień uruchamianie silnika działającego w ramach procesu, bez dodatkowego środowiska uruchomieniowego do obsługi.
  • Pamięć i strumieniowanie — jak silnik utrzymuje generowanie w ramach procesu ograniczone pod obciążeniem.
  • Generowanie w ramach procesu — tworzenie PDF wewnątrz tego samego procesu roboczego PHP, który obsługuje żądanie, bez podprocesu, gniazda ani zewnętrznej usługi.
  • Przyczepka — osobne środowisko uruchomieniowe działające obok twojej aplikacji, by wykonać jedno zadanie; tutaj zewnętrzny plik binarny, bezgłowa przeglądarka lub mikroserwis, który renderuje PDF poza twoim procesem.
  • Zimny start — opóźnienie i skok zużycia zasobów ponoszony, gdy podproces lub usługa muszą zostać uruchomione od zera, zanim będą mogły obsłużyć pierwsze żądanie.
  • IPC — komunikacja między procesami: potoki, gniazda, pliki tymczasowe lub wywołania sieciowe używane do przekazywania danych do i z osobnego procesu oraz powracające źródło kruchych, trudnych do debugowania awarii.
  • Styk delegowania do przeglądarki — opcjonalna, włączana świadomie ścieżka, która przekazuje renderowanie bezgłowej przeglądarce dla dokładnej wierności, z zablokowanym dostępem sieciowym do podzasobów; celowy wybór, a nie domyślne ustawienie.