Chrome 渲染器¶
ChromeRenderer 是 Artisan 的核心渲染引擎,透過 Chrome DevTools Protocol(CDP)控制 Chromium 無頭瀏覽器實例,將 HTML/CSS 轉換為 PDF bytes。渲染器設計為無狀態——每次渲染呼叫從 BrowserPool 取得連線、執行渲染、歸還連線,自身不持有任何瀏覽器狀態。
PHP Compatibility
This example uses PHP 8.5 syntax. If your environment runs PHP 8.1 or 7.4, use NextPDF Backport for a backward-compatible build.
CSS 支援範圍¶
ChromeRenderer 透過真實 Chromium 引擎渲染,因此支援所有現代 CSS 特性:
| CSS 特性 | 支援狀態 | 備註 |
|---|---|---|
| Flexbox | 完整支援 | CSS Flexible Box Layout Module Level 1 |
| Grid | 完整支援 | CSS Grid Layout Module Level 2 |
CSS 變數 (var()) | 完整支援 | Custom Properties |
| CSS Transforms | 完整支援 | 2D & 3D |
| Web Fonts | 完整支援 | woff2、system fonts |
@media print | 完整支援 | 建議搭配 @page 規則 |
| CSS Animations | 靜態快照 | 渲染為動畫第一幀 |
backdrop-filter | 完整支援 | 需 Chromium ≥ 76 |
建立渲染器¶
<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeRenderer;
use NextPDF\Artisan\BrowserPool;
use NextPDF\Artisan\Config\RendererConfig;
use NextPDF\Artisan\ValueObjects\PageFormat;
use NextPDF\Artisan\ValueObjects\PrintMargin;
$renderer = ChromeRenderer::create(
pool: $pool, // BrowserPool 實例
config: RendererConfig::create(
pageFormat: PageFormat::A4,
margin: PrintMargin::create(top: 15, right: 15, bottom: 15, left: 15),
printBackground: true,
preferCssPageSize: false,
scale: 1.0,
networkIdleTimeoutMs: 3000,
),
);
渲染方法¶
從 HTML 字串渲染¶
$pdfBytes = $renderer->renderHtml(
html: $htmlString,
pageFormat: 'A4',
waitForSelector: '.ready', // 可選:等待指定 CSS 選擇器出現
);
從 URL 渲染¶
$pdfBytes = $renderer->renderUrl(
url: 'https://internal.example.com/report/42',
headers: ['Authorization' => 'Bearer ' . $token],
networkIdlePolicy: 'networkIdle0', // 等待所有網路請求完成
);
從本機檔案渲染¶
$pdfBytes = $renderer->renderFile(
path: '/var/www/templates/invoice.html',
baseUrl: 'file:///var/www/templates/', // 解析相對資源路徑
);
CSP 沙箱安全¶
處理不受信任的 HTML 內容時,啟用 CSP 沙箱可防止 SSRF 與任意資源載入:
use NextPDF\Artisan\Config\CspPolicy;
use NextPDF\Artisan\Config\SandboxConfig;
$renderer = ChromeRenderer::create(
pool: $pool,
config: RendererConfig::create(
sandbox: SandboxConfig::create(
allowedOrigins: ['https://cdn.example.com'],
csp: CspPolicy::strict(), // 阻擋 inline scripts、外部 fetches
disableJavaScript: true, // 靜態文件建議停用 JS
disableExternalImages: false,
),
),
);
CDP 安全通道¶
ChromeRenderer 透過 WebSocket 連接 Chrome 的 CDP 端點。在生產環境中,應限制 CDP 監聽位址並設定連線認證:
use NextPDF\Artisan\Config\CdpConnectionConfig;
$pool = BrowserPool::create(
config: BrowserPoolConfig::create(
cdpConnection: CdpConnectionConfig::create(
host: '127.0.0.1', // 僅本機監聽
port: 9222,
connectTimeoutMs: 2000,
tlsEnabled: false, // 僅限內部網路使用 TLS 關閉
),
),
);
安全須知:CDP 端點具備完整瀏覽器控制能力,絕對不可暴露於公開網路。生產部署請使用 Unix domain socket 或 loopback 位址,並以防火牆規則限制存取。
逾時與重試策略¶
use NextPDF\Artisan\Config\RetryPolicy;
$renderer = ChromeRenderer::create(
pool: $pool,
config: RendererConfig::create(
renderTimeoutMs: 30000, // 單次渲染最長時間
retry: RetryPolicy::create(
maxAttempts: 2,
backoffMs: 500,
retryOnCrash: true, // 瀏覽器崩潰時重試
),
),
);
例外處理¶
| 例外類別 | 觸發條件 |
|---|---|
ChromeRenderException | CDP 通訊失敗、渲染逾時 |
BrowserPoolExhaustedException | 連線池已滿、取得逾時 |
SandboxViolationException | CSP 規則阻擋資源載入 |
PageCrashException | Chromium 頁面崩潰 |
參見¶
- Artisan 套件總覽 — BrowserPool、PdfParser 概覽
- PDF 解析器 — 渲染結果的後處理解析
- 頁面匯入 — 將渲染頁面匯入 Core 文件