O Node.js 26.5 trouxe Blob.textStream(), um método que entrega o texto de um Blob como ReadableStream. É uma adição pequena no changelog, mas conversa bem com uma direção que o runtime vem seguindo há algum tempo: fazer as APIs da plataforma web funcionarem de forma mais natural também no servidor.
Isso interessa quando o dado já chegou como Blob, por exemplo depois de um fetch(), e o próximo passo pode ser incremental. Em vez de pedir uma string completa logo de saída, o código pode consumir pedaços e encaixá-los em um pipeline de streams.
O que mudou, exatamente
A release 26.5.0 registrou blob.textStream() como mudança semver-minor. O método retorna uma ReadableStream de texto, então ele combina com APIs como pipeThrough(), TextDecoderStream e leitores assíncronos. A ideia não é substituir blob.text(); é escolher a forma de leitura que o restante do fluxo precisa.
const response = await fetch('https://exemplo.dev/relatorio.txt');
const blob = await response.blob();
for await (const chunk of blob.textStream()) {
process.stdout.write(chunk);
}
O exemplo parece trivial, e é justamente o ponto. Quando a origem já é um Blob, não é necessário converter para uma string enorme só para então voltar a trabalhar em blocos. Em serviços que fazem transformação de texto, inspeção de conteúdo ou encaminhamento de dados, esse encaixe reduz cola entre APIs.
Quando usar e quando não romantizar streams
Se o consumidor precisa do documento inteiro, await blob.text() continua mais direto e provavelmente mais legível. Um parser que recebe um JSON completo, por exemplo, não fica automaticamente melhor só porque o texto chegou em uma stream. Streams pagam quando há processamento progressivo, composição com outros fluxos ou quando a interface de destino já espera uma ReadableStream.
Também vale separar duas coisas que às vezes aparecem misturadas em exemplos: ler um Blob em chunks não significa que todo o caminho até ele foi necessariamente streaming. Se o código fez await response.blob(), a resposta já foi materializada como blob antes dessa etapa. Para processar uma resposta HTTP enquanto ela chega, o ponto de partida tende a ser response.body. O novo método resolve muito bem a etapa seguinte, não reescreve a física do buffering anterior.
Um pipeline mais explícito
O ganho aparece melhor quando a transformação é realmente incremental. Abaixo, cada linha de um export textual é tratada conforme o stream avança. Em produção, o divisor de linhas precisa lidar com chunks que terminam no meio de uma linha, então a função de transformação deve manter estado; usar split('\n') por chunk costuma parecer correto até o primeiro arquivo menos cooperativo.
const textStream = blob.textStream();
const normalized = textStream.pipeThrough(
new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.replaceAll('\r\n', '\n'));
},
}),
);
for await (const chunk of normalized) {
// Encaminhe, grave ou processe o trecho.
}
Há outra leitura interessante dessa release: ela também expõe ReadableStreamTee e acrescenta recursos em torno de streams. Não é uma razão para migrar um serviço inteiro para a versão Current, especialmente se ele depende de uma LTS. Mas é um sinal de que conhecer Web Streams deixou de ser uma habilidade exclusiva de quem escreve código de browser.
