23 pontos por GN⁺ 2025-08-04 | 3 comentários | Compartilhar no WhatsApp
  • O ambiente de desenvolvimento do Node.js passou por mudanças fundamentais nos últimos anos em termos de alta compatibilidade com os padrões da web e fortalecimento dos recursos nativos
  • Com a adoção de sistemas modernos de módulos e padrões assíncronos, como ESM(ES Modules), prefixo node: e top-level await, ficou mais fácil escrever código mais intuitivo e seguro
  • Muitos recursos agora são atendidos por APIs nativas, como Fetch API, AbortController e Web Streams, reduzindo a dependência de bibliotecas externas
  • Ferramentas nativas de desenvolvimento, como test runner, modo Watch e suporte a arquivos de ambiente, melhoram bastante a praticidade e a produtividade
  • Com o reforço da infraestrutura de segurança e deploy, incluindo controle de permissões, canais de diagnóstico e distribuição em executável único, o Node.js moderno está evoluindo para uma plataforma profissional e de uso geral

Mudanças e evolução do Node.js

  • O Node.js está deixando para trás sua estrutura inicial, centrada em callbacks e CommonJS, para se tornar um ambiente de desenvolvimento mais padronizado
  • Essa mudança não é apenas superficial, mas representa uma transformação no paradigma geral de desenvolvimento de JavaScript no lado do servidor

1. Sistema de módulos: padronização de ES Modules

  • CommonJS foi usado por muito tempo no Node.js, mas tem limitações em análise estática, tree shaking e incompatibilidades com os padrões da web
  • O modelo ESM(ES Modules) se consolidou como o novo padrão do Node.js
    • Uso da sintaxe import e export
    • Introdução do prefixo node: para distinguir explicitamente os módulos nativos
      • Exemplo: import { readFile } from 'node:fs/promises'
      • A distinção entre módulos nativos e pacotes npm fica mais clara
  • Com suporte a top-level await, agora é possível usar await no topo do módulo
    • Não há mais necessidade de envolver tudo em uma função assíncrona autoexecutável
    • O código fica mais linear e fácil de entender

2. APIs web nativas: menos dependências externas

  • A Fetch API passou a ser nativa no Node.js, permitindo fazer requisições HTTP sem dependências externas como Axios ou node-fetch
  • O Fetch oferece suporte nativo a timeout e cancelamento (AbortSignal.timeout())
    • Isso permite um tratamento de erros consistente sem bibliotecas adicionais para timeout
    Publicidade
  • Com AbortController, é possível implementar padrões de cancelamento em várias operações assíncronas, como arquivos e rede
    • Isso fornece uma forma padronizada de lidar com interrupções do usuário ou estouro de tempo

3. Testes nativos: ambiente profissional de testes

  • Sem depender de frameworks externos como Jest ou Mocha, o test runner nativo do Node.js já consegue atender à maioria das necessidades
    • Testes podem ser escritos de forma intuitiva com node:test e node:assert
  • Recursos voltados à produtividade, como modo Watch para testes e relatórios de cobertura, já vêm embutidos
    • Os testes são executados automaticamente sempre que o código é alterado
    • O Node.js 20 ou superior oferece recurso experimental de cobertura

4. Padrões assíncronos evoluídos

  • Embora async/await seja amplamente usado, o Node.js moderno enfatiza execução paralela e padrões mais refinados de tratamento de erros
    • Uso de Promise.all() para trabalhos paralelos e tratamento de erros com informações de contexto em um único try/catch
    Publicidade
  • O uso de AsyncIterator facilita o processamento sequencial de eventos e o controle de fluxo

5. Recursos avançados de streams e compatibilidade com padrões web

  • A API de streams passou a ter compatibilidade com o padrão web (Streams API)
    • Com Readable.fromWeb e Readable.toWeb, é possível converter streams entre Node.js e navegador
  • A função pipeline (baseada em Promise) permite montar pipelines de stream de forma intuitiva e segura

6. Worker Threads: processamento paralelo para tarefas intensivas de CPU

  • Com WorkerThreads, é possível superar a limitação de thread única do JavaScript e aproveitar múltiplos núcleos
  • Isso permite executar cálculos complexos ou processar grandes volumes de dados sem bloquear o loop principal

7. Revolução na experiência de desenvolvimento

  • A flag --watch detecta mudanças no código e reinicia automaticamente sem precisar de nodemon
  • A flag --env-file elimina a necessidade de dotenv e permite usar variáveis de ambiente imediatamente
  • A configuração do ambiente de desenvolvimento fica mais simples e rápida

8. Segurança e monitoramento de desempenho integrados

  • O Permission Model experimental permite restringir permissões da aplicação, como acesso a arquivos e rede
    • Isso ajuda a implementar o princípio do menor privilégio e facilita conformidade de segurança
  • Com perf_hooks, é possível medir desempenho nativamente, além de analisar e registrar automaticamente operações lentas
Publicidade

9. Modernização de deploy e empacotamento

  • Com suporte a SEA(Single Executable Application), é possível distribuir Node.js e a aplicação em um único binário
    • Isso facilita o deploy e a instalação mesmo em ambientes sem Node.js

10. Tratamento de erros e diagnóstico modernos

  • Classes de erro estruturadas permitem incluir contexto rico e informações de diagnóstico, entregando objetos de erro consistentes
  • Com diagnostics_channel, é possível transmitir dados de diagnóstico personalizados baseados em eventos e automatizar monitoramento

11. Evolução na resolução de módulos e no gerenciamento de pacotes

  • Com Import Maps, caminhos internos podem ser gerenciados em um namespace separado
    • Isso melhora a separação de módulos internos e facilita refatorações
  • Com import dinâmico, é possível carregar código em tempo de execução e fazer code splitting conforme o ambiente ou a configuração

Resumo principal e perspectivas futuras

  • No Node.js, é cada vez mais importante seguir os padrões da web, aproveitar ao máximo as ferramentas nativas e adotar padrões assíncronos modernos
  • Com Worker Threads e outros recursos de paralelismo de alto desempenho, além de funções de diagnóstico e segurança, ele está evoluindo para uma plataforma voltada a profissionais
  • Novos recursos como distribuição em executável único e namespaces de módulos aumentam bastante a praticidade operacional
  • Esses padrões podem ser adotados gradualmente, mantendo compatibilidade com código existente
  • Mesmo após 2025, o Node.js continuará evoluindo de forma constante, e esses padrões modernos apresentados aqui tendem a formar a base de aplicações orientadas ao futuro

3 comentários

 
sanori 2025-08-07

Quando comecei a criar projetos com Deno, pensei "uau, isso até faz isso", mas pelo visto o Node.js também está mudando de forma parecida.

 
dnltmdwhd 2025-08-05

Ah, agora nem precisa usar axios, dá pra usar fetch direto.

 
GN⁺ 2025-08-04
Opiniões do Hacker News
  • A maior mudança não é o ESM, e sim o fato de o Node agora trazer fetch e AbortController embutidos; consegui remover axios e node-fetch, reduzir o tamanho dos bundles de Lambda e ainda cortar cerca de 100 ms da latência de cold start; se você instala npm i axios por hábito, a release de Node de 2025 é o momento de parar
    • Prefiro ts-rest em toda a stack para cobrir tanto chamadas de API quanto validação; entre as bibliotecas baseadas em zod/json schema, ela é a mais leve e ao mesmo tempo oferece type safety robusta; também dá para plugar o cliente HTTP que você quiser (em bun e no engine do node escolho fastify); há algum overhead, mas vale muito a pena por mover a segurança de tipos para a etapa de compilação; queria saber se alguém conhece alternativas melhores ou tem outra opinião, porque procurei tudo o que consegui encontrar e só o ts-rest conseguiu equilibrar leveza e type safety
    • Não gosto tanto da sintaxe do fetch nem do trabalho extra de tratamento de exceções com await response.json e afins; com axios é bem mais intuitivo; até no código de exemplo, com axios basta lidar com response.data, enquanto com fetch você precisa checar o status manualmente e depois fazer o parse do JSON, o que é mais trabalhoso
    • Como autor de biblioteca, a adoção de ESM foi muito mais difícil e dolorosa, mas ainda assim foi um upgrade que valeu a pena; o fetch em si é ótimo, mas foi por causa do ESM que ganhamos muita coisa de verdade
    • O node fetch é muito mais fácil e simples que axios, então acho melhor; nem sabia que ainda tinha gente usando axios
    • Estou bem animado com o Undici, a biblioteca de requisições embutida; veja o site oficial do undici
  • Agora dá para executar limitando permissões de acesso ao sistema de arquivos ou à rede da seguinte forma
    # exemplo de restrição de acesso ao sistema de arquivos
    node --experimental-permission \
      --allow-fs-read=./data --allow-fs-write=./logs app.js
    
    # exemplo de restrição de rede
    node --experimental-permission \
      --allow-net=api.example.com app.js
    
    Parece ter sido inspirado no Deno; é um recurso excelente, veja a documentação de permissões do Deno
  • Agora também é possível estilizar texto diretamente sem instalar chalk ou picocolors
    const { styleText } = require('node:util');
    
    Veja a documentação oficial do styleText
  • Descobri várias coisas que já dá para aplicar imediatamente
    1. O Node agora tem testes embutidos, então não é mais necessário usar jest
    2. O Node também já traz watch embutido, então nodemon também deixa de ser necessário
    • Ainda prefiro jest, porque posso usar jest-extended
    • Acho que o sistema de testes embutido do Node deixa a desejar; se você usar por algumas semanas, vai entender por quê, e mesmo levantando issues o time do Node não parece dar muita atenção
  • Segundo Matteo Collina, o node fetch usa internamente o fetch do undici; como ele precisa criar WHATWG web streams, acaba sendo inerentemente mais lento que o modo request do undici,
    vídeo no YouTube citado,
    blog sobre como o undici funciona
    • Para quem tiver curiosidade, os benchmarks podem ser vistos aqui; testei recentemente em um MacBook Pro M3 Max, tanto em ambiente local quanto em rede, e o undici foi o melhor localmente, mas em rede o Axios teve resultados mais rápidos; não sei exatamente o motivo, mas minha experiência com o undici no último ano e meio foi excelente; dá para usar em produção com tranquilidade, mas se você quiser extrair o máximo de performance, precisa pensar de acordo com o contexto
  • Graças ao transpiler nativo de TypeScript do Node, quem usa TS teve uma boa redução de complexidade
    • Na verdade ele só remove tipos, não faz transpile de fato; coisas como enum do TS não funcionam direito
    • Ainda falta para uso real no dia a dia; não me importo com enum, mas ainda não dá para importar arquivos locais sem extensão, e também não dá para definir class properties no construtor
    • A flag --experimental-strip-types também não é mais necessária
  • Muitas vezes acabo descobrindo recursos novos por acaso; existe uma sensação vaga de “isso é novidade” como acontece no navegador; quando eu trabalhava só com C#, ficava realmente empolgado lendo sobre novos recursos da linguagem, mas hoje, como uso várias linguagens em paralelo, não é fácil acompanhar só uma; quase tudo vira aprendizado aleatório via blog ou influência de pessoas ao redor
    • Tenho bastante interesse nas novidades do Node (V8), então leio as release notes a cada 2 ou 3 meses para acompanhar esses recursos; às vezes também leio as ECMA proposals; queria muito que o pipeline operator entrasse
  • Fiquei um tempo afastado do ecossistema Node e, ao voltar, vi que surgiram muitos recursos novos realmente interessantes; acho que isso é resultado de Deno e Bun terem sacudido o mercado, fazendo a equipe do Node se esforçar ainda mais
  • O Node está cada vez mais se tornando um competidor de peso frente a Bun.js, Deno e outros; essa competição mútua é positiva para a evolução dos runtimes JS
    • As mudanças são lentas, mas constantes, e isso é bom de ver; ainda assim, continuo sentindo falta da shell function $ do Bun, porque usar JS como script é realmente muito conveniente, e eu não gostaria de manter os dois runtimes no servidor ao mesmo tempo
  • Assim como no navegador, acho que as novidades do Node podem ser divididas em dois tipos
    1. Tecnologias realmente novas
    2. Camadas de “embelezamento” adicionadas por cima de funcionalidades já existentes
      Também acho interessante observar em qual das duas as pessoas colocam mais peso
    • O que para alguém é uma “camada de embelezamento”, para outra pessoa pode ser ergonomia de uso