O navegador sempre soube processar HTML em partes durante o carregamento inicial. Depois que a página termina de ser analisada, porém, inserir uma resposta aos poucos em um ponto específico do DOM exige bem mais trabalho: buscar os dados, decodificar os chunks, montar elementos e decidir quando cada pedaço entra na tela.
O Chrome 155 começa a preencher essa lacuna com novos métodos de inserção e streaming de HTML. Em vez de esperar a resposta inteira ou construir a árvore manualmente, o código pode ligar um ReadableStream vindo do fetch() a um WritableStream fornecido pelo próprio elemento.
A versão estável está programada para 6 de outubro de 2026. Como o suporte começa pelo Chrome e a proposta maior ainda está evoluindo, a novidade merece teste e melhoria progressiva, não uma troca imediata de toda a arquitetura.
Uma família coerente de métodos para inserir HTML
A plataforma já acumulou várias formas de transformar texto em marcação: innerHTML, outerHTML, insertAdjacentHTML(), setHTML(), setHTMLUnsafe() e createContextualFragment(). Elas nasceram em momentos diferentes e não seguem uma convenção única para posição, sanitização e execução de scripts.
A nova API organiza as operações pelo efeito desejado. Há métodos estáticos como beforeHTML(), afterHTML(), prependHTML(), appendHTML() e replaceWithHTML(). Cada um recebe uma string e deixa explícito onde o conteúdo será colocado.
As versões de streaming seguem o mesmo vocabulário: streamBeforeHTML(), streamAfterHTML(), streamPrependHTML(), streamAppendHTML() e streamReplaceWithHTML(). Também existe streamHTML() para substituir o conteúdo do próprio elemento.
Da resposta HTTP direto para o parser
Os métodos de streaming devolvem um WritableStream. Isso permite usar a infraestrutura da Streams API que já existe no navegador. Um endpoint que responde fragmentos HTML pode ser conectado ao elemento assim:
const results = document.querySelector("#results");
const response = await fetch("/search?q=streams");
if (!response.ok || !response.body) {
throw new Error("Não foi possível carregar os resultados");
}
await response.body
.pipeThrough(new TextDecoderStream())
.pipeTo(results.streamHTMLUnsafe());
Enquanto os bytes chegam, o TextDecoderStream os transforma em texto e o parser insere o HTML progressivamente. Não é necessário concatenar todos os chunks para chamar innerHTML no final. Isso abre espaço para listas longas, resultados de busca, painéis e respostas produzidas aos poucos pelo servidor.
Também é possível obter um writer e enviar trechos manualmente. Nesse formato, cada write() alimenta o parser e close() encerra o fluxo:
const feed = document.querySelector("#feed");
const writer = feed.streamAppendHTMLUnsafe().getWriter();
await writer.write("<article><h2>Primeiro item</h2>");
await writer.write("<p>O conteúdo pode chegar em outro chunk.</p></article>");
await writer.close();
Por que existe uma versão “Unsafe”?
Os métodos sem o sufixo usam sanitização por padrão. Eles aceitam uma configuração ou uma instância da Sanitizer API para restringir elementos e atributos. As variantes Unsafe não aplicam esse filtro automaticamente e, por isso, tornam o risco visível no próprio nome da chamada.
“Unsafe” não significa que qualquer uso será explorado. Um fragmento estático produzido por um backend controlado tem uma origem diferente de um comentário enviado por usuário. Mesmo assim, interpolar conteúdo não confiável na resposta pode reabrir XSS. O servidor precisa escapar dados no contexto correto, e a aplicação deve preferir os métodos seguros quando a sanitização fizer parte do caso de uso.
As versões inseguras também recebem a opção runScripts, desativada por padrão. Ativar scripts transforma um fragmento de HTML em código executável e aumenta bastante a área de risco. Trusted Types e uma CSP bem configurada continuam relevantes; a API nova não substitui essas defesas.
Streaming não é atualização inteligente
O navegador passa a analisar e inserir o HTML, mas não faz reconciliação de componentes. Ele não compara uma árvore antiga com uma nova, não preserva automaticamente o estado de um formulário e não sabe qual parte da interface corresponde a um componente React, Vue ou Svelte. Dependendo do método escolhido, o conteúdo é substituído ou acrescentado.
Isso torna a API atraente para fragmentos em que o servidor já é a fonte da renderização: uma tabela que recebe novas linhas, uma busca que substitui os resultados ou um feed que acrescenta cards. Interfaces com muito estado local, edição otimista e interações acopladas ainda precisam de uma camada que coordene essas mudanças.
A parte declarativa é maior que o que está chegando agora
Os métodos fazem parte de um trabalho chamado Declarative Partial Updates. A proposta completa explora patches fora de ordem, marcações com <template>, atualização de regiões nomeadas e navegação no mesmo documento. Boa parte disso continua em discussão no Web Incubator Community Group.
O que o Chrome 155 lista para lançamento é a família renovada de métodos de inserção e streaming. Não convém tratar toda a visão declarativa como um padrão pronto e interoperável. Até o suporte chegar a outros navegadores, aplicações públicas precisam detectar a API e manter um caminho alternativo.
if ("streamHTMLUnsafe" in Element.prototype) {
// Usa o caminho progressivo.
} else {
// Busca a resposta completa e aplica a atualização compatível.
}
O polyfill publicado pelo time do Chrome ajuda a experimentar o formato das chamadas, mas ele acumula o conteúdo e aplica tudo ao final. Ou seja, não reproduz o principal benefício de renderizar conforme os chunks chegam.
Isso substitui SPA, HTMX ou frameworks?
Não sozinho. A API resolve uma operação de baixo nível: transformar um fluxo de texto HTML em nós inseridos numa posição conhecida. Roteamento, ciclo de vida, cache, formulários, estado, tratamento de erro e acessibilidade da interação continuam sendo decisões da aplicação ou do framework.
O ganho está em oferecer uma primitive nativa para arquiteturas que enviam HTML do servidor. Bibliotecas podem construir abstrações menores sobre ela, e projetos simples podem evitar uma pilha inteira só para atualizar um fragmento. Também reforça a ideia de uma web híbrida: o servidor continua renderizando, enquanto o navegador atualiza apenas a região necessária sem recarregar o documento inteiro.
Antes de adotar, vale responder três perguntas: o conteúdo pode aparecer progressivamente sem quebrar o layout? O estado dentro da região pode ser descartado? Existe fallback para navegadores sem suporte? Se as respostas forem claras, o streaming nativo pode retirar bastante código intermediário. Se não forem, a novidade apenas muda o lugar da complexidade.
