なぜ PDF エンジンはサイドカーではなく PHP に属するのか
Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7Spec: ISO 32000-2, §7ISO 32000-2 §7
PDF が作られる場所は二つあります。お使いの PHP プロセスの中か、あるいは、あなたが運用しなければならないどこか別の場所です。NextPDF はそれを内側で作ります。このページは、その選択の論証です — なぜプロセス内エンジンが通常は正しいデフォルトなのか、そして「どこか別の場所」というパターンが、プロダクションに入ったとき実際に何をもたらすコストなのか。
これはアーキテクチャの観点であって、フレームワークの観点ではありません。同じエンジンが Laravel、Symfony、CodeIgniter、そしてスタンドアロンのコードへどう届くかは別の物語であり、one engine, every framework で語られています。
なぜこれが重要か
「なぜこれが重要か」という見出しのセクションPDF 機能が、運用するシステムとして始まることはめったにありません。それはコントローラーの一行として始まります。この請求書をレンダリングする、あの帳票を返す、と。サイドカーパターンは、その一行をインフラに変えます。ドキュメントを描くために、あなたはいまや第二のものを動かします — 外部バイナリ、ヘッドレスブラウザー、別のマイクロサービス — そして、その第二のものが必要とするすべてが、あなたの問題にもなります。そのバージョン、そのメモリ、そのコンテナ、そのネットワーク、その障害モード、そして午前 2 時のそのオンコールページ。
そのコストはデモでは目に見えず、プロダクションでは避けられません。あなたのプロセスの中で生きるドキュメントエンジンは、そのどれも持ちません。問いは「サイドカーが PDF を作れるか」ではありません — もちろん作れます。それは「そこに至るために、あなたは何を運用すると契約したのか、そしてそれは必要だったのか」です。
- プロセス内とは、第二のランタイムがないということです。 NextPDF は、リクエストを処理したのと同じ PHP ワーカーの中で PDF を描きます。生成するサブプロセスも、デプロイするサービスも、生かし続ける余分なものもありません。
- サイドカーは、これまで持っていなかった運用上の面を加えます。 同梱されたブラウザーや外部バイナリは、独自のバージョン、独自のセキュリティフットプリント、独自のコンテナを持ち込み — そのすべてを、あなたはいまやパッチし、監視します。
- 物事が誤るのは、プロセス境界です。 コールドスタート、タイムアウト、脆いプロセス間配管、そしてデータがあなたのプロセスを離れること — これらは、プロセス内呼び出しが単純に持たない障害モードです。
- プロセス内はテスト可能で決定論的です。 エンジンは、ユニットテストし、モックし、推論できる、型付けされた PHP です — 動かして出力を見ることでしか探れない不透明なレンダラーではありません。
- 本物のブラウザーには、依然として本物の用途があります。 任意のモダンなウェブページのピクセル忠実なレンダリングには、ヘッドレスブラウザーが正直なツールです — そして NextPDF は意図的にそれへ委譲できます。それは接合点であって、デフォルトではありません。
NextPDF のアプローチ
「NextPDF のアプローチ」という見出しのセクション二つのアーキテクチャを並べて持ってみましょう。プロセス内のパスは一つの関数呼び出しです。サイドカーのパスは、ミニチュアの分散システムです — そして、そのボックスの間のあらゆる矢印は、あなたのコードとは独立して失敗する場所です。
- In-process: call the enginewriteHtml() or the document API runs inside the current PHP worker — no subprocess, no socket.
- In-process: receive PDF bytesThe engine returns native PDF content directly; nothing left the process.
- Sidecar: serialize and shipMarkup or a request is marshalled out of your process to a binary, browser, or remote service.
- Sidecar: cross the boundaryA process spawn or network hop — with a cold start, a timeout, and an IPC contract that can break.
- Sidecar: run a second runtimeAn external renderer with its own version, memory profile, and security surface to operate and patch.
- Sidecar: deserialize backMarshal the result back in and translate the renderer’s errors into yours.
運用すべき第二のランタイムがありません。 サイドカーパターンは、一つの機能の衣装をまとった二つのシステムです。同梱された wkhtmltopdf、ヘッドレス Chromium サービス、別のレンダリングマイクロサービス — そのそれぞれが、独自のリリース周期と独自のバグを持つランタイムです。あなたはそのすべてを引き継ぎます。プロセス内エンジンは Composer の依存関係として出荷されます。それは、あなたの composer.json 内の他のあらゆるライブラリと同じように更新され、デプロイメントにデーモン、イメージ、ソケットが加わることはありません。
バージョンドリフトと、より広いセキュリティの面。 同梱されたブラウザーは、絶え間ないセキュリティ勧告の流れを伴う、巨大で速く動くコードベースです。固定すれば朽ち、追従すれば変転します。いずれにせよ、それは一つのドキュメントを供給するために、レンダラーのウェブプラットフォーム全体があなたのサプライチェーンの中に座っている状態です。プロセス内の PHP エンジンは、あなたが読める、焦点の絞られたコードのライブラリです。そのセキュリティの面は、あなたがすでに動かしている PHP であって、いまさら加えて動かす第二のプラットフォームではありません。
データはあなたのプロセス境界の内側にとどまります。 シェルアウトすると、ドキュメントの内容 — それはしばしば、まさに PDF が運ぶために存在する機微なデータです — が境界を越えます。それはパイプ、引数、一時ファイル、あるいはサービスへのネットワークソケットに書き出されます。そのどれもが、漏洩する、うっかりログに記録される、あるいは残置される場所です。プロセス内では、データはそれを所有するワーカーを決して離れません。爆発半径は、艦隊ではなく、一つのプロセスです。
脆い配管、コールドスタート、そしてタイムアウト。 プロセス間およびネットワークの呼び出しは、関数呼び出しにはありえない仕方で失敗します。起動しなかったサブプロセス、ハングしたソケット、推測を誤ったタイムアウト、トラフィックの急増下でのコールドスタート。そのそれぞれが、リトライポリシー、サーキットブレーカー、そして予算を必要とします。プロセス内のレンダリングは、バイトを返すか、次の行で捕捉する型付き例外をスローするかのどちらかです。突き合わせるべき部分的なネットワーク状態はありません。
可観測性とテストは、境界を越えると難しくなります。 サイドカーの障害は、終了コード、切り詰められたログの一行、あるいはあなたが制御しないサービスからの 500 として届きます。それを再現するには、その環境全体を再現することになります。プロセス内エンジンは、あなたがすでに使っているツール — スタックトレース、デバッガー、プロファイラー — で可観測であり、あなたの残りの PHP と同じようにテスト可能です。そのテスト可能性は、名前の付いたソフトウェア品質特性です。ISO/IEC 25010 はそれを 保守性 の下に置き(Spec: ISO/IEC 25010:2023, §3.7ISO/IEC 25010:2023 §3.7)、プロセス内ライブラリは、起動することでしか動かせないレンダラーよりも、はるかに直接的にそれを満たします。
それらのテストが対象とする PDF は、ブラックボックスではなく、定義された構造です。PDF ファイルは、規定されたオブジェクトとファイルのレイアウトを持ち(Spec: ISO 32000-2, §7ISO 32000-2 §7)、プロセス内エンジンは、あなたが読めるコードからその構造を出力します — ですから、ゴールデンファイルテストや構造テストは、あなたが観察することしかできない外部プログラムの出力ではなく、既知の関数が生成したバイトを検査します。
要点全体がほんの数行に収まります。クライアントも、ベース URL も、ヘルスチェックも、リトライポリシーもありません — なぜなら、第二のシステムがないからです。
<?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();サイドカー版の形を対比してみてください — そのコードではなく、その 運用上の 形を。それは、バイナリやサービスがインストールされ到達可能であること、リクエストがシリアライズされ送信されること、タイムアウトが選ばれること、レンダラーがコールドあるいはダウンしているときの障害パス、そして結果がマーシャリングされ戻されることを必要とします。そのどれも、上のスニペットの中にはありません。なぜなら、エンジンがライブラリであるとき、そのどれも存在しないからです。
よくある誤解
「よくある誤解」という見出しのセクション頻繁に見られる思い込みは、「本物」の PDF レンダリングはブラウザーを意味するに違いない、ゆえにプロセス内はおもちゃ版に違いない、というものです。それはトレードオフを逆さまにしています。ブラウザーは、任意の モダンなウェブコンテンツの正確でピクセル忠実なレンダリングが必要なときに、正しいツールです。それは、ほとんどのチームが実際に行うドキュメント型の作業 — 請求書、帳票、明細書、契約書 — にとっては、誤ったデフォルトです。そこではレイアウトは既知であり、データはあなたのものであり、正しさは目ではなくバリデーターによって検査されます。その作業にとって、サイドカーの運用上の重みは、プロセス内エンジンがすでに与えていないものを何も与えてはくれず、上のセクションのすべてにおいてあなたにコストを払わせます。
鏡像となる誤解は、このページが犯さないよう注意しているものです。プロセス内エンジンがブラウザーのように「ウェブ全体」をレンダリングする、と主張することです。それはしませんし、NextPDF もそうであるふりはしません。そのプロセス内 HTML パイプラインは、ドキュメントレイアウトに焦点を当てた、仕様に整合したサブセットであり、文書化された境界を持ちます — 正直なスコープは the HTML pipeline に示されています。本当に完全なブラウザー忠実度が必要なときは、それは意図的でオプトインの委譲であって、暗黙のフォールバックではありません。
限界と境界
「限界と境界」という見出しのセクションプロセス内は正しいデフォルトです。それは、サブプロセスが決して正当化されないという普遍的な主張ではありません。ドキュメントが、プロセス内エンジンがカバーしない任意のモダンな CSS の正確なレンダリングを真に必要とするところでは、ヘッドレスブラウザーへ委譲することが正しい選択です — そして NextPDF は、そのパスを意図的に、ネットワークアクセスを制約したうえで、デフォルトではなく接合点としてサポートします。二つはライバルではありません。異なる仕事のための異なるツールです。
このページはアーキテクチャを論じるものであって、CSS のサポートマトリクスではありません。プロセス内パイプラインが正確にどの HTML と CSS をカバーするかは、エンジンのコードとその適合性テストによって定義され、そのパイプラインとともに文書化されます — ここで約束されるものではありません。「プロセス内」は、デフォルトのレンダリングパスを記述します。それは、あらゆる可能なパスがサブプロセスを回避するという主張ではありません。
機能の面はシンプルなままです。プロセス内エンジンは Core であり、ブラウザー委譲のパスはオプションの拡張機能であり、エディションとは独立しています。
| Edition | Availability |
|---|---|
| Core | Core renders PDF in-process in PHP — no subprocess, binary, or sidecar by default. |
| Pro | The headless-browser delegation path is an optional add-on extension, independent of edition tier. |
| Enterprise | The headless-browser delegation path is an optional add-on extension, independent of edition tier. |
関連ドキュメント
「関連ドキュメント」という見出しのセクション- The HTML pipeline — プロセス内エンジンの正直なスコープと、ブラウザーへの委譲が正しいのは正確にいつか。
- One engine, every framework — 補完的な軸:同じプロセス内エンジンが、スタックごとに別のライブラリを使うことなく、どうやってあらゆる PHP フレームワークへ届くか。
- Operating NextPDF in production — プロセス内エンジンを動かすことが、運用すべき余分なランタイムなしに、日々どう見えるか。
- Memory and streaming — エンジンが、負荷の下でプロセス内生成をどう有界に保つか。
- プロセス内生成 — リクエストを処理するのと同じ PHP ワーカーの中で、サブプロセス、ソケット、外部サービスなしに PDF を生成すること。
- サイドカー — 一つの仕事をするためにアプリケーションと並んで動く別のランタイム。ここでは、PDF をあなたのプロセスの外でレンダリングする外部バイナリ、ヘッドレスブラウザー、またはマイクロサービス。
- コールドスタート — サブプロセスやサービスが最初のリクエストに応じる前に、何もない状態から起動しなければならないときに生じるレイテンシとリソースの急増。
- IPC — プロセス間通信:別のプロセスとデータをやり取りするために使われるパイプ、ソケット、一時ファイル、あるいはネットワーク呼び出しであり、脆くデバッグの難しい障害が繰り返し生じる源。
- ブラウザー委譲の接合点 — サブリソースのネットワークアクセスをブロックした状態で、正確な忠実度のためにレンダリングをヘッドレスブラウザーに引き渡す、オプションのオプトインのパス。デフォルトではなく、意図的な選択。