Node.js 26: Temporal ligado por padrão, V8 14.6 e uma rodada de remoções

O Node.js 26.0.0 saiu em 5 de maio. Como toda versão par, ele começa como “Current” pelos próximos seis meses e, segundo o anúncio, entra em suporte de longo prazo (LTS) em outubro. Ou seja, é a versão que a maioria das equipes vai usar em produção a partir do fim do ano, e vale começar a testar agora.

Temporal, finalmente, sem flag

A novidade que mais me anima é simples de descrever: a API Temporal agora vem habilitada por padrão no Node.js 26. Quem já sofreu com o objeto Date do JavaScript, com meses começando em zero, fusos horários confusos e mutabilidade, sabe por que isso importa. O Temporal traz tipos separados para datas, horários, instantes e fusos, todos imutáveis.

Um exemplo mínimo, para pegar a data de hoje no calendário ISO:

const today = Temporal.Now.plainDateISO();
console.log(today.toString());

Não é preciso instalar polyfill nem passar flag na linha de comando. Um detalhe de bastidor: o build do Node agora inclui verificações de cargo e rustc por causa do Temporal, então quem compila o Node a partir do código-fonte vai precisar de um toolchain Rust.

V8 14.6 e novidades da linguagem

O motor JavaScript foi atualizado para o V8 14.6, a mesma versão do Chromium 146. Com ele chegam alguns recursos da linguagem que o anúncio destaca:

  • Upsert em mapas: getOrInsert() e getOrInsertComputed() em Map e WeakMap, que retornam o valor existente ou inserem um novo. Acaba o padrão repetitivo de checar com has, inserir com set e ler com get.
  • Sequenciamento de iteradores: Iterator.concat(), para encadear vários iteradores em um só.

O cliente HTTP Undici, que está por trás do fetch nativo, subiu para a versão 8.0.2. E o NODE_MODULE_VERSION passou a 147, o que significa que addons nativos precisam ser recompilados para esta versão.

O que foi removido

Uma versão major é também o momento de limpar a casa, e o Node 26 remove várias coisas que estavam depreciadas havia tempo:

  • http.Server.prototype.writeHeader() foi removido de vez. O substituto é writeHead().
  • Módulos legados de stream: _stream_wrap, _stream_readable, _stream_writable, _stream_duplex, _stream_transform e _stream_passthrough deixaram de existir.
  • --experimental-transform-types foi removida.

Além disso, a depreciação DEP0182, de criptografia, chegou ao fim da vida, e o module.register() passou a emitir aviso de depreciação em tempo de execução. Outras depreciações de criptografia e de streams também foram promovidas para aviso em tempo de execução.

Os módulos _stream_* são o tipo de coisa que ninguém usa diretamente hoje, mas que pode estar escondida em uma dependência antiga. Esse é o tipo de quebra que aparece na hora de atualizar sem que ninguém da equipe tenha escrito a linha problemática.

Mudanças de toolchain e plataformas

Para quem compila o Node ou mantém ambientes menos comuns, há mudanças importantes. O GCC mínimo passou a ser o 13.2, e o suporte ao Python 3.9 no build foi removido. O suporte às arquiteturas Power8 e IBM z13 foi descontinuado, e os builds para AIX e IBM i passam a mirar o Power 9.

Minha leitura

O Node.js 26 é uma versão de transição bem comportada. O Temporal habilitado por padrão é a mudança que vai aparecer no código das pessoas, e é uma melhoria real para qualquer aplicação que lida com datas. As novidades do V8 são pequenas, mas o getOrInsert vai limpar bastante código de cache e contagem.

O risco está nas remoções, e quase nunca no seu próprio código. Minha sugestão é rodar a suíte de testes no Node 26 agora, enquanto ele ainda é Current, para descobrir quais dependências usam writeHeader, módulos _stream_* ou module.register(). Quando a versão virar LTS em outubro, você já vai saber o que precisa ser atualizado, em vez de descobrir na pressa.

Fontes