Pipeline e serviços de build
BuildCommand cria BuildPipeline::default() e apenas formata o progresso. O pipeline recebe uma lista ordenada de objetos BuildStage, cria um BuildContext, executa cada estágio uma vez e acumula BuildStageResult em BuildReport.
O contexto transporta o nome do CSS gerado, os caminhos dos WOFF2 publicados para preload, o manifesto de assets de CompileAssetsStage/estágios de resolução para RenderPagesStage e o cache incremental opcional. Se um estágio lança exceção, não há captura no pipeline, relatório final ou execução dos estágios restantes.
Estágios padrão e delegados:
| Estágio | Serviço |
|---|---|
ValidateDependenciesStage |
BuildService::validateTailwindDependency(), PagefindService, MermaidRenderer e ShikiRenderer quando habilitados |
CleanDistStage |
BuildService::cleanDist() |
CompileAssetsStage |
BuildService::compileAssets() |
ResolveRevealJsStage |
RevealJsService |
ResolveRemixIconStage |
RemixIconService |
CopyFaviconAssetsStage |
BuildService::copyFaviconAssets() |
RenderPagesStage |
BuildService::renderPages() |
ResolvePagefindStage |
PagefindService |
GenerateMdxSourcesStage |
MdxSourceService |
GenerateFeedsStage |
FeedService |
GenerateSitemapStage |
SitemapService |
GenerateRobotsStage |
RobotsService |
GenerateLlmsTxtStage |
LlmsTxtService |
ValidateInternalLinksStage |
InternalLinkValidator |
GenerateCoversStage |
CoverService |
PrecompressOutputStage |
CompressionService |
BuildWarnings é um acumulador estático drenado pelos estágios de páginas e sitemap. Os serviços devolvem DTOs de resultado com itens gerados e tempo; os estágios os transformam em linhas e warnings de console.
RenderPagesStage grava rotas normais em <rota>/index.html, a home em
index.html e todas as rotas marcadas como páginas de erro em arquivos planos
<código>.html. /404 continua sendo obrigatório porque o router estático o
usa como fallback para caminhos desconhecidos; os demais códigos são publicados
quando suas fontes existem em Content/Pages/_errors/<código>/.
ResolveRemixIconStage roda depois de CompileAssetsStage. Quando habilitado, o RemixIconService prepara o CSS e as fontes em memória, registra todas as saídas no OutputRegistry e troca o namespace dist/assets/remixicon/ atomicamente. O manifest recebe css/remixicon.css, mantendo os layouts independentes dos hashes. No modo dev, Application só anuncia essa entrada quando a configuração está habilitada e o CSS está presente.
ResolvePagefindStage roda imediatamente depois de RenderPagesStage, pois
precisa dos HTML finais. Quando habilitado, PagefindService executa o binário
local sobre dist/, grava o índice em diretório temporário e troca
dist/pagefind/ atomicamente. O namespace é reservado no OutputRegistry para
impedir colisões com Content/public; sem o recurso, uma publicação antiga é
removida.
ValidateInternalLinksStage roda depois de todos os documentos auxiliares e antes das capas. InternalLinkValidator percorre cada HTML em dist/, resolve hrefs relativos e URLs HTTP(S) do mesmo domínio contra os arquivos publicados e verifica fragmentos somente quando o destino é HTML, usando id e a[name]. Isso permite links para saídas como feeds XML e fontes MDX. Links externos e esquemas não navegáveis ficam fora do escopo. Ao encontrar falhas, acumula os pares origem/destino e interrompe o build antes de publicar compressões ou capas.
ResolveRevealJsStage roda entre CompileAssetsStage e ResolveRemixIconStage
no pipeline padrão. RevealJsService respeita feature.revealjs e publica
reveal.mjs e reveal.css no namespace dist/assets/reveal/, com hashes no
build e nomes estáveis em public/assets/reveal/ no modo dev. O manifest
expõe essas saídas como js/reveal.js e css/reveal.css. Páginas MDX com
type: presentation geram a rota de artigo e uma segunda rota
<rota>/slides.html; a segunda usa o layout Reveal.js e é noindex com
canonical apontando para o artigo. O RouteCatalog resolve essa variante no
servidor dinâmico sem adicioná-la às rotas indexáveis.
Quando feature.mermaid está habilitado, ValidateDependenciesStage valida o
CLI Mermaid e o Chromium. Durante a descoberta MDX, o renderer customizado de
fences executa o mmdc e embute o SVG produzido no HTML do artigo e dos slides;
não há runtime Mermaid. Se Content/assets/css/mermaid.css existir, ele é
compilado como entrada CSS do usuário e registrado no manifest para ser carregado
pelos layouts.
Quando feature.shiki está habilitado, ValidateDependenciesStage valida
Node.js e o pacote local shiki. O ShikiRenderer mantém um worker Node por
build e encaminha a ele os fences de linguagens conhecidas; assim temas e
gramáticas são carregados uma vez e reutilizados por artigos e apresentações.
O worker devolve HTML com estilos inline e só existe durante o build: não há
asset, JavaScript ou runtime Shiki em dist/. Fences sem linguagem ou sem
gramática conhecida seguem o renderer CommonMark padrão.
Para um contrato passo a passo destinado a implementar a mesma arquitetura em outro projeto, consulte Criar e personalizar apresentações.
Os serviços que dependem de conteúdo recebem a mesma instância de RouteCatalog. O catálogo é lazy e vive somente durante o comando ou request, evitando repetir parsing e consultas Git sem manter dados obsoletos entre execuções. Seu resultado inclui as rotas e, somente para Collections opt-in, os documentos necessários a llms_full, feeds ou à publicação das fontes MDX. MdxSourceService grava os arquivos originais depois de renderizar as páginas e antes dos índices. GitFileDates resolve criação e modificação com um único histórico por arquivo e não abre processos Git quando nenhum repositório está montado.
ValidateDependenciesStage é sempre o primeiro estágio e verifica se
node_modules/.bin/tailwindcss existe e é executável. Quando habilitados,
Pagefind e Mermaid também são validados; Mermaid exige ainda um Chromium
executável. A mensagem do Tailwind inclui o pacote/versão esperados
(@tailwindcss/cli ^4.0.0) e orienta npm ci ou npm install; todas as
validações ocorrem antes de limpar dist/.
GenerateCoversStage pode ser removido da composição por --fast. No fluxo completo, CoverService inicia um php -S temporário sobre dist/, repassa ao renderer o manifesto de assets e o contexto de fontes (fontStylesheet e fontPreloads) usado pelas páginas, e mantém até --cover-jobs processos Chromium Headless ativos. O router estático aplica site.basePath exatamente como a publicação final e libera CORS para que o documento file:// carregue CSS, fontes e outros assets publicados. Cada resultado é comprimido com optipng -o2 -strip all; o servidor é encerrado mesmo quando uma cover falha. Com o cache incremental habilitado, a assinatura do HTML renderizado permite copiar covers inalteradas sem executar o Chromium.
PrecompressOutputStage percorre as saídas textuais e cria os sidecars .br
e .gz. O CompressionService identifica cada entrada pelo hash do conteúdo
e reutiliza os dois sidecars de storage/framework/build-cache/v1/ quando
disponíveis. O relatório do estágio informa hits e misses; --no-cache força
as compressões novamente sem ler ou escrever artefatos incrementais.
ServeService fica fora do pipeline. Ele resolve host/porta, gerencia o processo Tailwind e inicia o servidor PHP dinâmico ou estático. Generators também são separados: PageGenerator e ComponentGenerator escrevem templates em Content/ e seus Commands convertem exceções esperadas em código de falha.