ข้ามไปยังเนื้อหา
getnextpdf.com

เหตุใดเอนจิน PDF ของคุณจึงควรอยู่ใน PHP ไม่ใช่ sidecar

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

มีสองที่ที่ PDF ถูกสร้างได้: ภายในโพรเซส PHP ของคุณ หรือที่อื่นที่คุณต้องดำเนินการเอง NextPDF สร้างมันภายใน หน้านี้คือข้อโต้แย้งสำหรับทางเลือกนั้น — เหตุใดเอนจินแบบ in-process จึงมักเป็นค่าเริ่มต้นที่ถูกต้อง และรูปแบบ “ที่อื่น” นั้นมีต้นทุนเท่าไรจริงๆเมื่ออยู่ใน production

นี่คือมุมสถาปัตยกรรม ไม่ใช่มุมเฟรมเวิร์ก ส่วนเรื่องที่ว่าเอนจินตัวเดียวกันเข้าถึง Laravel, Symfony, CodeIgniter และโค้ดแบบสแตนด์อะโลนได้อย่างไรนั้นเป็นอีกเรื่องหนึ่ง เล่าไว้ใน เอนจินเดียว ทุกเฟรมเวิร์ก

ฟีเจอร์ PDF แทบไม่เคยเริ่มต้นเป็นระบบที่คุณต้องดำเนินการ มันเริ่มเป็นบรรทัดหนึ่งใน controller: เรนเดอร์ใบแจ้งหนี้นี้ ส่งรายงานนั้นกลับไป รูปแบบ sidecar เปลี่ยนบรรทัดนั้นให้เป็นโครงสร้างพื้นฐาน หากต้องการวาดเอกสาร ตอนนี้คุณต้องรันสิ่งที่สอง— ไบนารีภายนอก headless browser ไมโครเซอร์วิสที่แยกต่างหาก — และทุกอย่างที่สิ่งที่สองนั้นต้องการก็กลายเป็นปัญหาของคุณด้วย: เวอร์ชันของมัน หน่วยความจำของมัน คอนเทนเนอร์ของมัน เครือข่ายของมัน โหมดความล้มเหลวของมัน เพจเรียกเข้าเวรของมันตอนตีสอง

ต้นทุนมองไม่เห็นบนเดโม และเลี่ยงไม่ได้ใน production เอนจินเอกสารที่อยู่ในโพรเซสของคุณไม่มีต้นทุนเหล่านั้นเลยสักอย่าง คำถามไม่ใช่ “sidecar สร้าง PDF ได้หรือไม่” — แน่นอนว่าได้ แต่คือ “คุณรับปากจะดำเนินการอะไรเพื่อไปถึงตรงนั้น และคุณจำเป็นต้องทำไหม”

  • In-process หมายถึงไม่มีรันไทม์ที่สอง NextPDF วาด PDF ภายใน เวิร์กเกอร์ PHP ตัวเดียวกับที่จัดการคำขอนั้น ไม่มี subprocess ให้ spawn ไม่มีเซอร์วิสให้ deploy และไม่มีอะไรพิเศษให้คอยเลี้ยงให้มีชีวิตอยู่
  • sidecar เพิ่มพื้นผิวการดำเนินงานที่คุณไม่เคยมี browser ที่ bundle มา หรือไบนารีภายนอกพกเวอร์ชันของมันเอง รอยเท้าความปลอดภัยของมันเอง และ คอนเทนเนอร์ของมันเองมาด้วย — ซึ่งทั้งหมดนี้ตอนนี้คุณต้องแพตช์และเฝ้าดู
  • ขอบเขตของโพรเซสคือจุดที่สิ่งต่างๆพังลง cold start, timeout, การต่อท่อ ระหว่างโพรเซสที่เปราะ และข้อมูลที่ออกไปจากโพรเซสของคุณ คือโหมดความล้มเหลว ที่การเรียกแบบ in-process ไม่มีเลย
  • In-process ทดสอบได้และเป็นแบบกำหนดผลล่วงหน้าได้ เอนจินคือ PHP แบบมีชนิด ที่คุณ unit-test, mock และให้เหตุผลกับมันได้ — ไม่ใช่ renderer ทึบที่คุณ สำรวจได้เพียงด้วยการรันมันแล้วดูผลลัพธ์
  • browser จริงก็ยังมีประโยชน์จริง สำหรับการเรนเดอร์หน้าเว็บสมัยใหม่ใดๆ อย่างซื่อตรงทุกพิกเซล headless browser คือเครื่องมือที่ซื่อตรง — และ NextPDF มอบหมายงานให้มันได้โดยจงใจ มันคือรอยต่อ ไม่ใช่ค่าเริ่มต้น

วางสถาปัตยกรรมสองแบบไว้ข้างกัน เส้นทาง in-process คือการเรียกฟังก์ชัน เส้นทาง sidecar คือระบบกระจายขนาดจิ๋ว — และทุกลูกศรระหว่างกล่องของมันคือจุดที่ล้มเหลวเป็นอิสระจากโค้ดของคุณ

  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.
เส้นทาง in-process เทียบกับเส้นทาง sidecar แบบ in-process นั้น PDF ถูกสร้างโดยการเรียกแบบมีชนิดภายในเวิร์กเกอร์ PHP ตัวเดียวกันและส่งคืนโดยตรง ส่วนเส้นทาง sidecar เพิ่มขั้นตอน serialization ขอบเขตของโพรเซสหรือเครือข่าย รันไทม์ภายนอกที่มีเวอร์ชันและรอยเท้าของมันเอง และขั้นตอน deserialization กลับ — แต่ละอย่างคือโหมดความล้มเหลวที่แตกต่างซึ่งการเรียกแบบ in-process ไม่มี

ไม่มีรันไทม์ที่สองให้ดำเนินการ รูปแบบ sidecar คือสองระบบที่สวมเครื่องแต่งกายของฟีเจอร์เดียว wkhtmltopdf ที่ bundle มา เซอร์วิส headless Chromium ไมโครเซอร์วิสเรนเดอร์ที่แยกต่างหาก — แต่ละตัวคือรันไทม์ที่มีจังหวะการปล่อยของมันเองและบั๊กของมันเอง คุณรับสืบทอดมันมาทั้งหมด เอนจินแบบ in-process ส่งมาในรูป Composer dependency มันถูกอัปเกรดในแบบเดียวกับไลบรารีตัวอื่นๆทุกตัวใน composer.json ของคุณ โดยไม่มี daemon, image หรือ socket เพิ่มเข้ามาใน deployment ของคุณ

Version drift และพื้นผิวความปลอดภัยที่กว้างขึ้น browser ที่ bundle มาคือ codebase ขนาดใหญ่ที่เคลื่อนที่เร็วพร้อมกระแสคำเตือนด้านความปลอดภัยที่ไม่ขาดสาย ปักหมุดมันไว้แล้วมันก็ผุ ตามมันไปแล้วมันก็ปั่นป่วน ไม่ว่าทางใดมันก็คือ web platform ทั้งแพลตฟอร์มของ renderer ที่นั่งอยู่ใน supply chain ของคุณเพื่อป้อนเอกสารเดียว เอนจิน PHP แบบ in-process คือไลบรารีของโค้ดที่โฟกัสซึ่งคุณอ่านได้ พื้นผิวความปลอดภัยของมันคือ PHP ที่คุณรันอยู่แล้ว ไม่ใช่แพลตฟอร์มที่สองที่ตอนนี้คุณต้องรันด้วย

ข้อมูลอยู่ภายในขอบเขตโพรเซสของคุณ เมื่อคุณ shell out เนื้อหาเอกสาร — ซึ่งมักเป็นข้อมูลอ่อนไหวพอดีที่ PDF มีไว้เพื่อพกพา — ข้ามขอบเขต มันถูกเขียนลง pipe, argument, temp file หรือ network socket ไปยังเซอร์วิส ทุกอันคือจุดที่จะรั่ว ถูกบันทึกไว้โดยบังเอิญ หรือถูกทิ้งค้างไว้ แบบ in-process ข้อมูลไม่เคยออกไปจากเวิร์กเกอร์ที่เป็นเจ้าของมัน รัศมีการระเบิดคือหนึ่งโพรเซส ไม่ใช่ทั้งกองเรือ

การต่อท่อที่เปราะ cold start และ timeout การเรียกระหว่างโพรเซสและผ่านเครือข่ายล้มเหลวในแบบที่การเรียกฟังก์ชันทำไม่ได้: subprocess ที่ไม่เริ่ม socket ที่ค้าง timeout ที่คุณเดาผิด cold start ภายใต้คลื่นทราฟฟิกที่พุ่งสูง แต่ละอย่างต้องการนโยบาย retry, circuit breaker และงบประมาณ การเรนเดอร์แบบ in-process ไม่ก็ส่งคืนไบต์ หรือไม่ก็โยน typed exception ที่คุณ catch ในบรรทัดถัดไป ไม่มีสถานะเครือข่ายบางส่วนให้ต้องปรับให้ตรงกัน

Observability และการทดสอบยากขึ้นเมื่อข้ามขอบเขต ความล้มเหลวใน sidecar มาถึงในรูป exit code, บรรทัด log ที่ถูกตัดทอน หรือ 500 จากเซอร์วิสที่คุณไม่ได้ควบคุม การทำให้มันเกิดซ้ำหมายถึงการทำให้สภาพแวดล้อมนั้นทั้งหมดเกิดซ้ำ เอนจินแบบ in-process สังเกตได้ด้วยเครื่องมือที่คุณใช้อยู่แล้ว — stack trace, debugger, profiler — และทดสอบได้ในแบบเดียวกับ PHP ส่วนที่เหลือของคุณ ความสามารถในการทดสอบนั้นคือคุณสมบัติด้านคุณภาพซอฟต์แวร์ที่มีชื่อ: ISO/IEC 25010 วางมันไว้ภายใต้ maintainability (Spec: ISO/IEC 25010:2023, §3.7) และไลบรารีแบบ in-process ก็ทำให้มันสำเร็จได้ตรงกว่า renderer ที่คุณออกแรงกับมันได้เพียงด้วยการเปิดใช้มันเท่านั้น

PDF ที่การทดสอบเหล่านั้นยืนยันคือโครงสร้างที่นิยามไว้ ไม่ใช่กล่องดำ ไฟล์ PDF มีเลย์เอาต์ของออบเจกต์และไฟล์ที่ระบุไว้ (Spec: ISO 32000-2, §7) และเอนจินแบบ in-process สร้างโครงสร้างนั้นจากโค้ดที่คุณอ่านได้ — ดังนั้นการทดสอบแบบ golden-file หรือเชิงโครงสร้างจึงตรวจไบต์ที่ฟังก์ชันที่รู้จักสร้างขึ้น แทนที่จะเป็นผลลัพธ์ของโปรแกรมภายนอกที่คุณสังเกตได้เท่านั้น

ประเด็นทั้งหมดอยู่ในไม่กี่บรรทัด ไม่มี client ไม่มี base URL ไม่มี health check และไม่มีนโยบาย retry — เพราะไม่มีระบบที่สอง

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

ลองเทียบรูปทรงของเวอร์ชัน sidecar — ไม่ใช่โค้ดของมัน แต่รูปทรง เชิงการดำเนินงาน ของมัน มันต้องการไบนารีหรือเซอร์วิสที่ติดตั้งและเข้าถึงได้ คำขอที่ serialize แล้วส่ง timeout ที่เลือกไว้ เส้นทางความล้มเหลวสำหรับเมื่อ renderer เย็นหรือล่ม และผลลัพธ์ที่ marshal กลับมา ไม่มีสิ่งใดในนั้นอยู่ใน snippet ข้างบน เพราะไม่มีสิ่งใดในนั้นมีอยู่เมื่อเอนจินคือไลบรารี

ข้อสันนิษฐานที่พบบ่อยคือการเรนเดอร์ PDF “ของจริง” ต้องหมายถึง browser ดังนั้น in-process จึงต้องเป็นเวอร์ชันของเล่น นั่นเข้าใจการแลกได้แลกเสียกลับด้าน browser คือเครื่องมือที่ถูกต้องเมื่อคุณต้องการการเรนเดอร์เนื้อหาเว็บสมัยใหม่ ใดๆ อย่างเป๊ะและซื่อตรงทุกพิกเซล มันคือค่าเริ่มต้นที่ผิดสำหรับงานรูปทรงเอกสารที่ทีมส่วนใหญ่ทำกันจริง — ใบแจ้งหนี้ รายงาน ใบแจ้งยอด สัญญา — ที่เลย์เอาต์เป็นที่รู้กัน ข้อมูลเป็นของคุณ และความถูกต้องตรวจโดยตัวตรวจสอบความถูกต้อง ไม่ใช่ด้วยตา สำหรับงานนั้น น้ำหนักเชิงการดำเนินงานของ sidecar ไม่ได้ซื้ออะไรให้คุณที่เอนจินแบบ in-process ไม่ได้ให้อยู่แล้ว และทำให้คุณเสียทุกอย่างในหัวข้อด้านบน

ความเข้าใจผิดในกระจกเงาคือสิ่งที่หน้านี้ระวังที่จะไม่ทำ: การอ้างว่าเอนจินแบบ in-process เรนเดอร์ “ทั้งเว็บ” ได้เหมือน browser มันทำไม่ได้ และ NextPDF ก็ไม่แสร้งว่าทำได้ ไปป์ไลน์ HTML แบบ in-process ของมันคือชุดย่อยที่สอดคล้องกับข้อกำหนดซึ่งโฟกัสที่การจัดวางเอกสาร พร้อมขอบเขตที่มีเอกสารกำกับ — ขอบเขตที่ซื่อตรงวางไว้ใน ไปป์ไลน์ HTML เมื่อคุณต้องการความซื่อตรงระดับ browser เต็มรูปแบบจริงๆ นั่นคือการมอบหมายแบบเลือกใช้โดยจงใจ ไม่ใช่การสำรองทางแบบเงียบๆ

In-process คือค่าเริ่มต้นที่ถูกต้อง มันไม่ใช่การอ้างแบบครอบจักรวาลว่า subprocess ไม่มีวันมีเหตุผลรองรับ ในที่ที่เอกสารต้องการการเรนเดอร์ CSS สมัยใหม่ใดๆอย่างเป๊ะซึ่งเอนจินแบบ in-process ไม่ครอบคลุมจริงๆ การมอบหมายให้ headless browser คือทางเลือกที่ถูกต้อง — และ NextPDF รองรับเส้นทางนั้นโดยจงใจ โดยจำกัดการเข้าถึงเครือข่ายของมัน ในฐานะรอยต่อ ไม่ใช่ค่าเริ่มต้น ทั้งสองไม่ใช่คู่แข่ง แต่เป็นเครื่องมือคนละอย่างสำหรับงานคนละอย่าง

หน้านี้โต้แย้งเรื่องสถาปัตยกรรม ไม่ใช่ตารางการรองรับ CSS ส่วนที่ว่าไปป์ไลน์ in-process ครอบคลุม HTML และ CSS ตัวใดบ้างนั้น ถูกนิยามโดยโค้ดของเอนจินและการทดสอบความสอดคล้องของมัน และมีเอกสารกำกับไว้พร้อมกับไปป์ไลน์นั้น — ไม่ได้สัญญาไว้ที่นี่ “In-process” อธิบายเส้นทางการเรนเดอร์ค่าเริ่มต้น มันไม่ใช่การอ้างว่าทุกเส้นทางที่เป็นไปได้เลี่ยง subprocess

พื้นผิวความสามารถยังคงเรียบง่าย: เอนจินแบบ in-process คือ Core และเส้นทางการมอบหมายให้ browser เป็นส่วนขยายแบบเลือกได้ ที่เป็นอิสระจากรุ่น

Where the PDF is rendered — edition availability
EditionAvailability
CoreCore renders PDF in-process in PHP — no subprocess, binary, or sidecar by default.
ProThe headless-browser delegation path is an optional add-on extension, independent of edition tier.
EnterpriseThe headless-browser delegation path is an optional add-on extension, independent of edition tier.
  • ไปป์ไลน์ HTML — ขอบเขตที่ซื่อตรงของ เอนจินแบบ in-process และเวลาที่การมอบหมายให้ browser ถูกต้องพอดี
  • เอนจินเดียว ทุกเฟรมเวิร์ก — แกนที่เสริมกัน: วิธีที่เอนจินแบบ in-process ตัวเดียวกันเข้าถึงทุกเฟรมเวิร์ก PHP โดยไม่ต้องมีไลบรารีต่างกันต่อหนึ่งสแตก
  • การดำเนินงาน NextPDF ใน production — การรันเอนจินแบบ in-process มีหน้าตาอย่างไรในแต่ละวัน โดยไม่มีรันไทม์ เพิ่มเติมให้ดำเนินการ
  • หน่วยความจำและการสตรีม — วิธีที่ เอนจินรักษาการสร้างแบบ in-process ให้มีขอบเขตจำกัดภายใต้ภาระงาน
  • In-process generation — การสร้าง PDF ภายในเวิร์กเกอร์ PHP ตัวเดียวกัน ที่จัดการคำขอ โดยไม่มี subprocess, socket หรือเซอร์วิสภายนอก
  • Sidecar — รันไทม์ที่แยกต่างหากซึ่งรันควบคู่ไปกับแอปพลิเคชันของคุณเพื่อทำ งานเดียว ในที่นี้คือไบนารีภายนอก headless browser หรือไมโครเซอร์วิสที่เรนเดอร์ PDF นอกโพรเซสของคุณ
  • Cold start — ความหน่วงและการพุ่งของทรัพยากรที่เกิดขึ้นเมื่อ subprocess หรือเซอร์วิสต้องถูกเริ่มจากศูนย์ก่อนที่มันจะให้บริการคำขอแรกได้
  • IPC — inter-process communication คือ pipe, socket, temp file หรือ การเรียกผ่านเครือข่ายที่ใช้ส่งข้อมูลไปและกลับจากโพรเซสที่แยกต่างหาก และเป็น แหล่งความล้มเหลวที่เปราะและดีบักยากซ้ำๆ
  • Browser-delegation seam — เส้นทางแบบเลือกใช้โดยจงใจที่ส่งการเรนเดอร์ให้ headless browser เพื่อความซื่อตรงที่เป๊ะ โดยบล็อกการเข้าถึงเครือข่ายของ subresource เป็นทางเลือกโดยจงใจ ไม่ใช่ค่าเริ่มต้น