Edge 渲染¶
EdgeRenderer 是 nextpdf/cloudflare 的核心元件,負責在 Cloudflare Workers 的無狀態、無檔案系統、CPU 時間受限的環境中執行 NextPDF Core 生成 PDF。
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.
渲染模式¶
EdgeRenderer 支援兩種渲染模式,根據文件複雜度與 CPU 時間預算自動切換:
| 模式 | 說明 | 適用場景 |
|---|---|---|
| Full Mode | 完整 NextPDF Core 功能 | 複雜度低到中的文件 |
| Lightweight Fallback | 預先渲染的模板 + 動態資料填充 | CPU 超時或複雜文件 |
建立 EdgeRenderer¶
<?php
declare(strict_types=1);
use NextPDF\Cloudflare\EdgeRenderer;
use NextPDF\Cloudflare\Config\EdgeRendererConfig;
use NextPDF\Cloudflare\Fallback\LightweightTemplateFallback;
$renderer = EdgeRenderer::create(
config: EdgeRendererConfig::create(
maxCpuMs: 20000, // 目標 CPU 時間(ms),超出則觸發 fallback
maxMemoryMb: 100, // 記憶體上限感知(MB)
fallbackOnTimeout: true, // CPU 超時時自動降級
fallbackOnMemoryPressure: true,
fallback: LightweightTemplateFallback::fromFile(
templatePath: __DIR__ . '/templates/fallback.pdf',
),
),
);
渲染 PDF¶
基本渲染¶
use NextPDF\Core\Document;
$pdfBytes = $renderer->render(function (Document $doc): void {
$doc->addPage();
$doc->text('Cloudflare Edge PDF', x: 20, y: 30, fontSize: 18);
$doc->text('Generated at: ' . date('Y-m-d H:i:s'), x: 20, y: 50);
});
在 Worker Handler 中使用¶
<?php
declare(strict_types=1);
use NextPDF\Cloudflare\EdgeRenderer;
use NextPDF\Cloudflare\Http\WorkerResponse;
// Cloudflare Workers PHP Runtime 的請求處理器
function handle(array $request): array
{
$renderer = EdgeRenderer::create(EdgeRendererConfig::default());
$pdfBytes = $renderer->render(function (\NextPDF\Core\Document $doc): void {
$doc->addPage()->text('Hello from Edge', x: 20, y: 30);
});
return WorkerResponse::pdf(
bytes: $pdfBytes,
filename: 'edge-document.pdf',
disposition: 'attachment',
);
}
Fallback 策略¶
當 PDF 生成超出 CPU 預算或記憶體壓力過高時,EdgeRenderer 自動觸發 fallback:
use NextPDF\Cloudflare\Fallback\FallbackStrategyInterface;
use NextPDF\Cloudflare\Fallback\LightweightTemplateFallback;
use NextPDF\Cloudflare\Fallback\StaticPdfFallback;
use NextPDF\Cloudflare\Fallback\RedirectFallback;
// 策略 1:以輕量模板填充資料(推薦)
$fallback = LightweightTemplateFallback::fromBytes($templatePdfBytes)
->withDataInjector(function (\NextPDF\Artisan\PageImport\FormFiller $filler, array $data): void {
$filler->fill('customer_name', $data['name']);
$filler->fill('invoice_total', number_format($data['total'], 2));
});
// 策略 2:回傳靜態預先生成的 PDF
$fallback = StaticPdfFallback::fromR2Key('fallback/generic-invoice.pdf');
// 策略 3:重定向至伺服器端生成端點
$fallback = RedirectFallback::to('https://api.example.com/pdf/generate');
CPU 時間監控¶
use NextPDF\Cloudflare\Monitoring\CpuTimer;
$timer = CpuTimer::start();
$pdfBytes = $renderer->render(function (\NextPDF\Core\Document $doc) use ($timer): void {
foreach ($this->pages as $index => $pageData) {
$doc->addPage();
$doc->text($pageData['content'], x: 20, y: 30);
// 提前檢查是否接近 CPU 上限
if ($timer->elapsedMs() > 15000) {
throw new \NextPDF\Cloudflare\Exception\CpuBudgetExceededException(
"Stopping at page {$index} to avoid CPU timeout",
);
}
}
});
$cpuUsed = $timer->stop(); // CpuTimerResult
WorkerResponse 輔助類別¶
use NextPDF\Cloudflare\Http\WorkerResponse;
// PDF 下載回應(含 OWASP 標頭)
return WorkerResponse::pdf(
bytes: $pdfBytes,
filename: 'document.pdf',
disposition: 'attachment', // 或 'inline'
);
// 包含自訂標頭
return WorkerResponse::pdf(
bytes: $pdfBytes,
filename: 'document.pdf',
additionalHeaders: [
'X-Generation-Time-Ms' => (string) $cpuUsed->totalMs(),
'CF-Cache-Status' => 'MISS',
],
);
例外處理¶
| 例外類別 | 觸發條件 |
|---|---|
CpuBudgetExceededException | CPU 時間超出設定上限 |
MemoryPressureException | 記憶體使用量超出設定上限 |
FallbackFailedException | Fallback 策略本身也失敗 |
EdgeRenderException | 一般性渲染失敗 |
參見¶
- Cloudflare 套件總覽 — 套件架構與 Workers 限制
- R2 封存 — 將生成的 PDF 封存至 R2
- API 保護 — 速率限制與認證