O Node vem com dezenas de módulos que não precisam de npm install - fs, http, path, crypto, e mais são compilados diretamente no binário do node.
Coletivamente, essa é a biblioteca padrão do Node, e ela é grande o suficiente para que um serviço de backend funcional muitas vezes possa ir longe antes de precisar de sua primeira dependência de terceiros.
Noções Básicas de APIs Embutidas cobre os módulos de uso diário com código funcional; esta página é o mapa acima disso - o que realmente distingue um "embutido" de um pacote npm, como o Node organiza e estabiliza essas APIs ao longo do tempo, e por que uma parcela crescente delas agora espelha as APIs da Plataforma Web do navegador em vez de inventar formas exclusivas para o Node.
Módulos embutidos são código compilado diretamente no binário do Node e resolvidos através de um registro interno, não através de uma busca baseada em disco em node_modules - e a documentação do Node marca cada um com um nível de Índice de Estabilidade que informa o quão seguro é depender dele.
Por que Importa: Saber se uma API é um módulo estável nativo do Node, uma API da Plataforma Web adotada, ou uma adição experimental muda a confiança com que você pode construir sobre ela e como ela se comportará ao atualizar o Node.
Conceitos Chave:módulo embutido, prefixo node:, Índice de Estabilidade, API nativa do Node, API da Plataforma Web, binding interno.
Quando Usar Este Modelo: Decidir se uma necessidade já é coberta pelo próprio Node antes de buscar o npm, raciocinar sobre se uma API é segura para confiar a longo prazo, depurar erros de TypeScript em torno de tipos embutidos, e ler as páginas de fs, crypto, path, os/process, timers, e util com a moldura correta.
Limitações / Compromissos: Os embutidos versionam com o próprio runtime do Node, não independentemente - atualizar o Node pode mudar o comportamento dos embutidos mesmo quando as dependências do seu package.json não mudaram nada.
Tópicos Relacionados: resolução de módulos, especificadores de módulo node:, TypeScript no Node, o event loop.
Um módulo embutido é código-fonte que é enviado compilado dentro do executável node em vez de um arquivo em disco que precisa ser localizado e carregado.
Essa é a distinção principal de qualquer coisa no npm: solicitar fs ou crypto nunca toca na busca de resolução de node_modules do sistema de arquivos - o Node reconhece o nome e entrega a funcionalidade de seu próprio registro interno, instantaneamente.
O Node adotou o prefixo explícito node: (import fs from 'node:fs') para remover qualquer ambiguidade entre um embutido e um pacote com o mesmo nome que alguém poderia teoricamente publicar no npm.
O prefixo é opcional para a longa lista de módulos principais originais por compatibilidade retroativa, mas é obrigatório para adições mais recentes como node:test e node:sea, e é o padrão que as orientações atuais recomendam em geral, pois torna a origem de um módulo inequívoca à primeira vista.
Uma analogia útil: módulos embutidos são como as utilidades públicas de uma cidade - água, energia, estradas.
Eles estão sempre presentes, padronizados, e você não os "instala" da maneira que contrataria um empreiteiro particular (um pacote npm); eles vêm com o fato de morar na cidade, e a própria cidade (a versão do Node) decide quando e como eles mudam.
import { readFile } from 'node:fs/promises'; // Nativo do Node: API da era de callbacks, promisificadaimport { randomUUID } from 'node:crypto'; // Nativo do Node: helpers de criptografia focados em servidorconst res = await fetch('https://example.com'); // API da Plataforma Web: mesma forma que o navegador
Cada API documentada do Node carrega uma classificação de Índice de Estabilidade que governa quanta mudança você deve esperar: APIs Experimentais podem mudar ou desaparecer entre versões menores, APIs Estáveis só quebram em um lançamento Node semver-major, e APIs Legado são mantidas, mas ativamente desencorajadas em favor de uma substituição mais nova.
Noções Básicas de APIs Embutidas cobre como realmente ler esse marcador na documentação; o modelo mental aqui é o que ele implica para seu código - uma API Experimental em produção é um risco deliberado, não uma falha.
As mecânicas de carregamento diferem fundamentalmente dos pacotes npm: um especificador embutido resolve através de uma busca de binding interno embutida no runtime, então não há I/O de disco, nenhuma resolução de campo main de package.json, e nenhuma dependência das configurações do sistema de módulos do seu projeto além de se você está usando sintaxe CJS ou ESM.
É por isso também que os embutidos são versionados com o próprio binário do Node em vez de independentemente - um recurso como util.parseEnv ou o fetch global só existe quando você está em uma versão do Node que o incluiu, independentemente do que está fixado em package.json.
A biblioteca padrão na verdade se divide em duas famílias distintas que se comportam de maneira diferente na prática.
APIs nativas do Node - fs, http, net, cluster - foram projetadas especificamente para o mundo do Node do lado do servidor, orientado a callbacks e EventEmitter, muitas vezes modeladas em chamadas de sistema POSIX, e não têm equivalente em um navegador.
APIs da Plataforma Web Adotadas - fetch, URL, URLSearchParams, structuredClone, AbortController, e crypto.webcrypto - são a implementação do Node das mesmas interfaces que os navegadores expõem, deliberadamente moldadas para corresponder, para que o mesmo código possa rodar no Node, em um navegador, ou em outro runtime JS como Deno ou Bun sem um shim de compatibilidade.
Essa convergência é uma mudança estratégica real, não cosmética: versões anteriores do Node resolviam cada problema com uma API específica do Node (http.get para chamadas de rede), enquanto versões recentes preferem cada vez mais enviar o equivalente padrão da Web (fetch) ao lado ou em vez de inventar algo novo.
O efeito prático é que pacotes isomorfos - bibliotecas destinadas a rodar tanto no Node quanto no navegador - podem depender mais da plataforma diretamente, sem empacotar um polyfill para coisas que o Node agora fornece nativamente.
O próprio processo de depreciação do Node é uma parte de primeira classe deste modelo: APIs depreciadas emitem avisos de runtime (visíveis via --pending-deprecation para APIs que ainda não avisam por padrão), dando às equipes uma janela para migrar antes que uma API seja realmente removida em uma futura versão major.
Esse processo é parte do que "Estável" deveria significar - mesmo APIs Estáveis podem eventualmente ser depreciadas, mas apenas através de um caminho documentado e versionado em vez de uma mudança silenciosa que quebra a compatibilidade.
O modelo de segurança também difere significativamente das dependências npm.
Módulos embutidos são enviados através do próprio processo de lançamento e aviso de segurança do Node, sem registro, sem nome de pacote para typosquatting, e sem árvore de dependência transitiva para auditar - o que é uma razão real para preferir um embutido a um pacote npm equivalente quando um existe, além de apenas evitar uma instalação.
Isso não torna os embutidos livres de riscos (o próprio Node recebe CVEs, e o uso indevido de um embutido como child_process ainda é uma classe comum de vulnerabilidade) - apenas move o limite de confiança de "milhares de mantenedores em um registro público" para "a equipe principal do Node".
Observabilidade e diagnóstico são um canto subutilizado da biblioteca padrão que vale a pena mencionar aqui: módulos como node:perf_hooks, node:diagnostics_channel, e node:async_hooks existem especificamente para instrumentar processos Node em produção sem adicionar uma dependência de tracing, e frameworks como Express e Fastify, juntamente com a maioria dos ORMs e drivers de banco de dados, são construídos diretamente sobre node:http, node:net, e node:tls.
TypeScript é um caso especial que vale a pena destacar: como os embutidos são bindings compilados em C++ expostos como objetos JavaScript, eles não carregam nenhuma informação de tipo própria da maneira que um arquivo .ts escrito à mão faria.
O pacote @types/node é um conjunto mantido separadamente de arquivos de declaração que descreve a forma de cada embutido - é por isso que é uma devDependency em praticamente todos os projetos TypeScript do Node, e por que sua versão deve acompanhar a versão do Node que você realmente tem como alvo.
Fonte
Força
Fraqueza
Melhor Encaixe
Embutido nativo do Node (fs, http, crypto)
Sem instalação, sem risco de cadeia de suprimentos, versiona com o runtime
Forma de API específica do Node, às vezes ergonomia da era de callbacks
I/O do lado do servidor, necessidades de nível de SO e de processo
API da Plataforma Web Adotada (fetch, URL)
Mesma forma do navegador, portável entre runtimes
Adições mais recentes podem atrasar a paridade de recursos do navegador
Código isomorfo, clientes HTTP simples, manipulação de URL
Pacote npm
Preenche lacunas que os embutidos não cobrem, ecossistema de movimento mais rápido
Risco real de cadeia de suprimentos e manutenção, outra dependência para auditar
Qualquer coisa genuinamente fora do escopo da biblioteca padrão.
"Se não está no npm, tenho que escrever eu mesmo." Uma quantidade surpreendente de necessidades comuns já é coberta por embutidos - geração de UUID, clientes HTTP, análise de env, e estilização de terminal são enviados no Node moderno sem instalar nada.
"O prefixo node: é obrigatório para todos os módulos principais." É opcional para os módulos estabelecidos há muito tempo (fs, path, http) por compatibilidade retroativa, mas é obrigatório para os mais novos como node:test e node:sea.
"Módulos embutidos nunca mudam ou quebram." Cada embutido carrega um Índice de Estabilidade, e APIs Experimentais ou Legado podem mudar ou ser removidas em um cronograma muito mais curto do que "nunca".
"APIs da Plataforma Web se comportam identicamente no Node e no navegador." A forma corresponde deliberadamente, mas as semânticas podem diferir - o fetch do Node não tem aplicação de CORS e comportamento de agente/proxy padrão diferente do fetch de um navegador.
"TypeScript entende embutidos do Node imediatamente." Não entende - embutidos são bindings compilados sem informação de tipo inerente, que é exatamente o que @types/node existe para fornecer.
O que torna um módulo "embutido" em vez de algo que você instala?
Ele é compilado diretamente no binário do Node e resolvido através de um registro interno em vez de uma busca em node_modules no disco - sem etapa de instalação, sem busca de rede, sem versão para fixar independentemente do próprio Node.
Preciso do prefixo `node:` em todas as importações de módulos principais?
Não - é opcional em módulos estabelecidos há muito tempo como fs e path por compatibilidade retroativa, mas as adições mais recentes (node:test, node:sea) o exigem, e usá-lo consistentemente é a prática recomendada atual de qualquer forma.
O que o Índice de Estabilidade realmente me diz?
Ele me diz quanta mudança esperar: APIs Experimentais podem mudar entre versões menores do Node, APIs Estáveis só quebram em um aumento de versão major, e APIs Legado são mantidas, mas ativamente desencorajadas em favor de algo mais novo.
Por que o Node tem tanto `node:http` quanto o `fetch` global?
node:http é o primitivo de rede original e focado em servidor do Node; fetch é uma adição posterior que espelha a API do navegador especificamente para que o mesmo código cliente possa rodar sem modificação no Node, navegadores e outros runtimes JS.
Os embutidos são versionados separadamente dos pacotes no meu `package.json`?
Não - os recursos e o comportamento disponíveis de um embutido estão inteiramente ligados à versão do Node que você está executando, razão pela qual atualizar o Node pode mudar o que está disponível, mesmo que nenhuma dependência do package.json tenha mudado.
Por que preciso de `@types/node` se o TypeScript já entende JavaScript?
Embutidos são bindings compilados em C++ expostos como objetos JS simples, então eles não carregam informações de tipo embutidas da maneira que uma fonte .ts escrita à mão faria - @types/node é um conjunto mantido de arquivos de declaração descrevendo suas formas.
É mais seguro usar um embutido do que um pacote npm equivalente?
Geralmente sim do ponto de vista da cadeia de suprimentos - embutidos são enviados através do próprio processo de lançamento e segurança principal do Node, sem registro, sem risco de typosquatting, e sem árvore de dependência transitiva para auditar, embora os próprios embutidos ainda possam ter seus próprios CVEs.
O `fetch` global do Node se comporta exatamente como o de um navegador?
Ele corresponde à mesma forma de API deliberadamente, mas o ambiente de runtime difere - o fetch do lado do servidor não tem aplicação de CORS e configuração de rede padrão diferente (proxies, agentes) do que um contexto de navegador.
Como o Node me avisa antes de remover uma API depreciada?
APIs depreciadas emitem avisos de depreciação em tempo de execução, e o flag --pending-deprecation expõe avisos para APIs que ainda não avisam por padrão - dando às equipes uma janela documentada para migrar antes de uma remoção eventual.
Por que frameworks como Express são construídos sobre `node:http` em vez de substituí-lo?
node:http já lida com o ciclo de vida de requisição/resposta de baixo nível e gerenciamento de sockets; frameworks adicionam roteamento, middleware e ergonomia por cima, em vez de reimplementar primitivas de rede que o Node já fornece.
Qual é um exemplo de necessidade específica do Node sem equivalente na Plataforma Web?
Preocupações de processo e nível de SO - iniciar processos filhos, forking para múltiplos núcleos de CPU, ler a memória do host e informações de CPU - não têm análogo no navegador, já que navegadores não têm conceito de um processo de sistema operacional para expor.