Artisan em produção
Visão geral
Seção intitulada “Visão geral”Em produção, injete um renderizador configurado e um logger PHP Standards Recommendation 3 (PSR-3), reutilize o processo ativo do Chrome entre renderizações, defina alturas explícitas para documentos com múltiplos elementos e limite o caminho de renderização com um timeout upstream.
Visão conceitual
Seção intitulada “Visão conceitual”BrowserPool mantém ativo um processo do Chrome (keepAlive: true) e o reinicia a cada 100 renderizações para limitar o crescimento de memória, um padrão de acúmulo conhecido em clientes Chrome DevTools Protocol (CDP) de longa duração. Para um worker que renderiza muitos documentos, use um único renderizador de longa duração em vez de um renderizador por requisição, para que você pague o custo de inicialização do Chrome apenas raramente.
Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”<?php
declare(strict_types=1);
use NextPDF\Artisan\ChromeHtmlRenderer;use NextPDF\Artisan\ChromeRendererConfig;use NextPDF\Artisan\Exception\ChromeNotAvailableException;use NextPDF\Artisan\Exception\ChromeRenderException;use Psr\Log\LoggerInterface;
final class ReportRenderer{ private ChromeHtmlRenderer $renderer;
public function __construct(LoggerInterface $logger) { $config = ChromeRendererConfig::fromArray([ 'chrome_binary' => getenv('CHROME_BINARY') ?: null, 'render_timeout' => 45, 'max_html_size' => 2_000_000, 'no_sandbox' => (bool) getenv('CHROME_NO_SANDBOX'), ]);
$this->renderer = new ChromeHtmlRenderer($config, $logger); }
public function render(string $html, float $widthPt, float $heightPt = 0.0): string { try { return $this->renderer->render($html, $widthPt, $heightPt)->getPdfData(); } catch (ChromeNotAvailableException $e) { // Deployment fault: Chrome runtime missing. Page the on-call owner. throw $e; } catch (ChromeRenderException $e) { // Render-time fault: timeout, crash, empty output. Retryable once. throw $e; } }
public function shutdown(): void { $this->renderer->close(); }}Crie o renderizador uma vez e depois o reutilize. Chame close() quando o worker for encerrado para liberar o processo do Chrome de forma determinística, em vez de esperar pelo destrutor. Os dois ramos de catch separam uma falha de implantação (runtime ausente) de uma falha em tempo de renderização (passível de nova tentativa). Não use blocos catch vazios.
Conecte-o a um container como um singleton:
$container->singleton(ReportRenderer::class, fn ($c) => new ReportRenderer($c->get(Psr\Log\LoggerInterface::class)));Tratamento de altura
Seção intitulada “Tratamento de altura”Quando você omite a altura, a ponte mede a altura do conteúdo no Chrome (max das alturas de scroll e offset de body/document), converte o valor em pontos e adiciona uma margem de segurança de ~0.2 polegada (~14.4 pt). Essa margem cobre a diferença entre o layout de viewport do Chrome e o reflow do seu layout de impressão. Sem ela, o printToPDF pode fazer o conteúdo transbordar para uma segunda página que o PageImporter (apenas a página 0) recortaria. A ponte impõe uma altura mínima de papel de 0.1 polegada. Os testes ChromeHtmlRendererTest::renderUsesAutoFitHeightByDefault, ::renderAutoFitBufferIsAddedNotSubtracted e ::renderAppliesMinimumHeightOf0Point1InchForTinyExplicitHeight asseguram esse comportamento.
Para documentos de layout fixo (faturas, certificados), passe uma altura explícita em pontos. Quando a altura é explícita, nenhuma margem é adicionada, e a saída corresponde exatamente ao tamanho de papel solicitado (garantido por ::renderHonorsExplicitHeightWithoutAutoBuffer).
Workers em lote
Seção intitulada “Workers em lote”- Crie um renderizador por worker e o reutilize.
BrowserPoolreutiliza o navegador ativo e reinicia automaticamente no limite de 100 renderizações. - Chame
close()no encerramento do worker e entre lotes grandes quando quiser um processo do Chrome novo antes do limite de 100 renderizações. - O destrutor chama
close(), mas umclose()explícito é determinístico e preferível em processos de longa duração. - Os avisos de reinício são registrados no nível
noticecom a contagem de renderizações; gere um alerta diante de uma taxa de reinício elevada, pois ela indica documentos mais pesados do que o esperado.
Observabilidade
Seção intitulada “Observabilidade”Injete um logger PSR-3. O renderizador emite estes eventos e níveis:
| Evento | Nível | Contexto |
|---|---|---|
| Início da renderização | debug | size, width, height |
| Renderização concluída | debug | pdfSize, contentHeight |
| Inicialização do navegador | info | binary |
| Reinício do navegador | notice | count |
| Fechamento do navegador | debug | renderCount |
Nenhum HTML, byte de PDF ou texto extraído é registrado em log. Isso mantém os payloads fora dos logs operacionais e está alinhado com a orientação de conteúdo de log da National Institute of Standards and Technology Special Publication (NIST SP) 800-92. Crie objetivos de nível de serviço (SLOs) de latência a partir do par start/complete e um alerta de taxa de reinício a partir dos eventos notice.
Padrões de implantação
Seção intitulada “Padrões de implantação”- Chrome sidecar: execute o Chrome no mesmo container que o worker PHP; fixe
chrome_binary. Provisione um container com suporte a sandbox; consulte /integrations/artisan/chrome-renderer-setup/. - Sem container / CLI: o Artisan não tem container de injeção de dependência. Use
EInvoiceServiceFactorypara contratos de e-invoice do Premium em runners de command-line interface (CLI); consulte /integrations/artisan/boot-and-discovery/. - Limitação de recursos: combine
render_timeoutcom um orçamento de requisição upstream e um cgroup/ulimit de host. Consulte o modelo de ameaças em /integrations/artisan/security-and-operations/.
Casos extremos e armadilhas
Seção intitulada “Casos extremos e armadilhas”- Um renderizador interrompido no meio de uma renderização ainda fecha a página do Chrome (
finally), e o pool permanece utilizável. - Reutilizar um renderizador entre threads/processes não é suportado; cada renderizador é dono de um processo do Chrome.
- O reinício a cada 100 renderizações é fixo; dimensione os lotes levando isso em conta para que os picos de latência permaneçam previsíveis.
Desempenho
Seção intitulada “Desempenho”O custo em regime permanente é o layout do conteúdo de entrada pelo Chrome mais o printToPDF, não a sobrecarga da ponte. O keepAlive distribui o custo de inicialização entre as renderizações. Espere um pico de latência a cada 100ª renderização (reinício do processo); exponha esse pico nos SLOs em vez de tratá-lo como um incidente.
Notas de segurança
Seção intitulada “Notas de segurança”Os caminhos de produção recebem HTML não confiável. Releia /integrations/artisan/security-and-operations/. As barreiras de rede permanecem ativas independentemente da configuração, mas no_sandbox: true remove o isolamento de processo do Chrome e aumenta o nível de confiança exigido para a entrada.
Contexto comercial
Seção intitulada “Contexto comercial”Em workers sem container, EInvoiceServiceFactory retorna null quando o Premium não está instalado, de modo que o caminho de renderização open-source permanece inalterado. Instale o Pro/Enterprise para habilitar a incorporação e a validação de e-invoice no documento renderizado.
Veja também
Seção intitulada “Veja também”- /integrations/artisan/quickstart/
- /integrations/artisan/configuration/
- /integrations/artisan/security-and-operations/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/