- Recentemente, o Node.js vem evoluindo rapidamente ao incorporar ao runtime recursos que antes só eram possíveis com pacotes npm
- Isso permite reduzir riscos de segurança na cadeia de suprimentos, melhorar a portabilidade do código, diminuir dependências e simplificar a manutenção, além de contribuir para garantir desempenho e estabilidade em ambientes de produção
- Com a adição de APIs globais como
fetch(), WebSocket e node:test, agora é possível desenvolver sem pacotes famosos como node-fetch, ws e mocha
- A expansão dos recursos do sistema de arquivos trouxe opções em
fs.glob(), fs.rm() e fs.mkdir() que substituem glob, rimraf e mkdirp
- Nas APIs utilitárias e de criptografia,
crypto.randomUUID(), util.styleText(), atob/btoa e outras já fazem parte do padrão, tornando desnecessários pacotes como uuid e chalk
- Alguns recursos (
node:sqlite, URLPattern, --env-file, execução de TypeScript etc.) ainda permanecem em fase experimental
- O ponto importante é que, com a própria evolução do Node.js, já é possível desenvolver aplicações modernas apenas com o runtime padrão
Principais pacotes npm substituídos por recursos nativos do Node.js
- Durante muito tempo, o Node.js dependeu de diversos pacotes npm para utilitários HTTP, helpers de sistema de arquivos e outras funções
- Porém, nas versões recentes (v18~v22), a tendência de integrar esses recursos diretamente ao runtime vem se fortalecendo
- Com isso, há uma redução na complexidade do gerenciamento de pacotes e na exposição a riscos de segurança
1. node-fetch → Global fetch()
- Desde o Node.js 18, o mesmo
fetch() do navegador é fornecido como função global
- É possível fazer requisições HTTP sem
node-fetch
- Foi introduzido experimentalmente na v17.5.0 e estabilizado na v18.0.0
- No entanto, em versões anteriores à 18,
node-fetch ainda é necessário
2. ws → Global WebSocket
- Desde o Node.js 21, a classe global
WebSocket dá suporte a conexões WebSocket no lado do cliente
- Adicionada experimentalmente na v21.0.0, segue em fase experimental até agora
- Para implementação de WebSocket no lado do servidor, ainda é necessário usar o pacote
ws ou bibliotecas relacionadas
3. Frameworks de teste → node:test
- Desde o Node.js 18, há o runner de testes nativo
node:test, que pode substituir mocha, jest e outros
- Introduzido experimentalmente na v18.0.0 e estabilizado na v20.0.0
- Suporta escrita e execução de testes unitários básicos
- Se forem necessários snapshots, mocking e plugins mais completos, frameworks de terceiros ainda são úteis
- Ele é suficiente para testes em nível de módulo, mas frameworks tradicionais ainda têm vantagens no desenvolvimento de aplicações full stack
4. sqlite3 / better-sqlite3 → node:sqlite
- O Node.js está introduzindo o módulo experimental
node:sqlite para acesso ao SQLite
- Resolve problemas de compilação e erros em upgrades comuns em pacotes com bindings nativos
- Suporta tarefas básicas como criar bancos de dados em memória e criar tabelas
- Como ainda está em fase experimental, é recomendável usar pacotes da comunidade quando forem necessários ajustes avançados de desempenho ou recursos adicionais
5. chalk / kleur → util.styleText()
- Desde o Node.js 20.12.0, é possível fazer estilização de texto no console com
util.styleText()
- Estabilizado na v22.17.0
- Aplica estilos básicos como cor, negrito e sublinhado
- Se forem necessários temas complexos, sintaxe encadeada e compatibilidade retroativa, ainda é possível continuar usando
chalk e similares
6. strip-ansi → util.stripVTControlCharacters()
- O Node.js fornece nativamente a função de remover códigos de escape ANSI
- Permite remover com segurança caracteres de controle de logs
- A maioria dos casos de uso já é coberta nativamente, tornando desnecessários pacotes de terceiros
7. glob → fs.glob()
- Desde o Node.js 22, foi adicionado o recurso nativo
fs.glob() para busca por padrões de arquivos
- Adicionado na v22.0.0 e estabilizado na v22.17.0 LTS
- Permite buscar arquivos com padrões glob como
**/*.js
- Se for necessária compatibilidade com versões antigas do Node.js, use o pacote
glob
8. rimraf → fs.rm({ recursive: true })
- A remoção recursiva de diretórios é suportada pela API nativa do Node.js
- Implementada com as opções
recursive e force de fs.rm()
- Disponível desde aproximadamente a v12.10.0 e estabilizada em todas as versões LTS atuais
- É possível remover diretórios com segurança sem o pacote
rimraf
9. mkdirp → fs.mkdir({ recursive: true })
- A criação recursiva de diretórios é fornecida pela opção
recursive de fs.mkdir()
- Adicionada desde a v10.12.0 e estabilizada há bastante tempo
- É possível criar diretórios aninhados sem pacote adicional
10. uuid → crypto.randomUUID()
- Desde o Node.js 14.17.0, existe a função de geração de UUID
crypto.randomUUID()
- Incluída como um recurso estável do módulo de criptografia
- É possível gerar IDs aleatórios seguros sem o pacote
uuid
11. base64-js / atob → atob, btoa
- Desde o Node.js 20, as funções globais
atob e btoa estão disponíveis
- A mesma API de codificação/decodificação Base64 do navegador
- Oferece uma opção adicional além do
Buffer tradicional
- É possível processar Base64 sem polyfill
12. url-pattern → URLPattern
- Desde o Node.js 20, a API global
URLPattern é oferecida experimentalmente
- Dá suporte a route matching, extração de parâmetros de caminho e mais
- Ainda está em fase experimental e precisa de estabilização
- É possível tratar correspondência de padrões de URL com uma Web API padrão
13. dotenv → flag --env-file
- Desde o Node.js 20.10.0, há suporte ao carregamento de variáveis de ambiente com a flag
--env-file
- Carrega diretamente o arquivo
.env na execução
- Ainda está em fase experimental
- Para recursos avançados como expansão de variáveis e múltiplos arquivos env, o pacote
dotenv ainda é necessário
14. event-target-shim → EventTarget
- Desde o Node.js 15.0.0, o Node.js fornece globalmente o sistema de eventos padrão da Web,
EventTarget
- Estabilizado na v15.4.0
- Suporta o mesmo modelo de tratamento de eventos do navegador
- Pode ser usado como alternativa ao
EventEmitter
15. tsc → execução de TypeScript no Node.js
- Desde o Node.js 21, é possível executar arquivos
.ts diretamente com a flag --experimental-strip-types
- Apenas remove tipos; não oferece verificação de tipos completa
- Ainda está em fase experimental
- Para builds de produção, checagem estática de tipos, geração de arquivos de declaração e verificação completa de tipos,
tsc ainda é necessário
Conclusão
- A direção da evolução do Node.js é reduzir a dependência de pacotes externos e elevar a completude da própria plataforma
- Na versão LTS mais recente (v22), muitos pacotes npm já se tornaram desnecessários,
o que representa uma grande melhoria em segurança, desempenho e manutenibilidade
- Em ambientes operacionais corporativos, soluções como N|Solid estão sendo usadas para monitorar essas mudanças em tempo real
- Análise do desempenho em cargas reais de recursos nativos (
fetch, node:test, crypto.randomUUID() etc.)
- O agente de IA N|Sentinel fornece monitoramento de uso e recomendações de otimização em nível de código
6 comentários
As APIs fornecidas pelo runtime estão aumentando cada vez mais..
Especialmente APIs de rede, URL, b64 e APIs de processamento de strings, entre outras...
Isso é totalmente... PH..
Parece que o UUID v7 ainda é cedo demais.
Acho que drivers de banco de dados precisam ser vistos por uma perspectiva diferente de recursos que deveriam entrar em outras bibliotecas padrão; tanto no Bun quanto aqui, qual seria o motivo para querer embutir um driver de SQLite no runtime?
Será que é porque o Python já traz isso embutido?
Em vez de embutir funcionalidades de SQLite, acho mais importante criar um padrão de interface para drivers de banco de dados.
Como a interface muda de driver para driver, não é esse o problema que torna difícil dar suporte a bancos heterogêneos sem usar ORM?
Acho que colocaram isso porque, para serviços pequenos, no nível de um blog pessoal, muitas vezes só o sqlite já é suficiente. É útil de ter.
Acho que colocaram o sqlite porque ele tem a interface mais simples e serve como uma boa referência para consulta.
E também não sei por que seria necessário criar esse padrão de interface para drivers de banco de dados que você mencionou. Tenho a vaga lembrança de já ter visto algo parecido em PHP.
Como ainda uso consultas RAW para queries complexas que o ORM não consegue resolver...
Pelo visto você usa vários tipos diferentes de banco de dados com frequência... que tal criar uma biblioteca? :)
Em runtimes como Python, Java, C#, Go etc., é bem comum haver uma padronização da interface de drivers de banco de dados.
Mas no Node, até entre drivers voltados para o mesmo SQLite, a execução de statements muda entre
execute()eexec(), então até trocar apenas o driver já exige certo nível de modificação.Não é algo que acontece com frequência, mas quando é preciso trocar de banco também é inconveniente.
Se você estiver usando MySQL e passar a não gostar do que a Oracle faz, ou precisar muito de alguma extensão do PostgreSQL e decidir migrar para ele,
em casos com interface padrão como o JDBC basta validar o SQL, mas no ecossistema Node há o efeito colateral de ter que refazer toda a lógica de chamadas ao banco.
+Você me recomendou criar uma biblioteca, mas para isso ajuda muito existir um padrão de interface comum.
Na empresa usamos Java, e no framework interno precisamos dar suporte a MySQL, DB2, Oracle e MSSQL, então na manutenção dos adaptadores de cada banco eu já me beneficiei bastante do padrão JDBC.