Server Runtime

Fundamentos de Node.js

Node.js executa JavaScript fora do navegador, no servidor. Seu I/O não bloqueante e seu ecossistema vasto o tornam a escolha natural para APIs, ferramentas e apps full-stack.

beginner15 min readUpdated 15 de set. de 2026
server.js
js
// server.js
import { createServer } from "node:http";

const server = createServer((req, res) => {
  if (req.url === "/health") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ status: "ok" }));
    return;
  }
  res.writeHead(404).end("Not found");
});

server.listen(3000, () => {
  console.log("http://localhost:3000");
});
Primeiro lançamento
2009, por Ryan Dahl
Engine
V8
Modelo
Não bloqueante, orientado a eventos
Módulos
ESM e CommonJS
Pacotes
registro npm
Ideal para
APIs, ferramentas, apps em tempo real

Por que importa

Por que o Node.js é importante

JavaScript no servidor

Use a mesma linguagem em ambos os lados da conexão, o que simplifica equipes, ferramentas e o compartilhamento de código.

I/O não bloqueante

O event loop continua processando requisições enquanto aguarda arquivos, redes e bancos de dados, mantendo o throughput alto.

Um ecossistema massivo

O npm fornece pacotes para quase qualquer tarefa, e frameworks como Express e Fastify tornam a criação de APIs rápida.

O panorama completo

As três ideias por trás do Node.js

Um motor JavaScript, um event loop não bloqueante e uma biblioteca padrão para arquivos, redes e processos.

O runtime

Executar

V8 mais as APIs do Node para arquivos, rede, processos e timers.

O event loop

Agendar

Uma única thread, uma fila de callbacks e chamadas de sistema não bloqueantes.

O ecossistema

Estender

O registro npm fornece frameworks, bibliotecas e ferramentas de linha de comando.

Node.js em resumo

O núcleo do Node.js

Servidor HTTP

Construa uma API com o módulo http nativo ou com um framework.

Sistema de arquivos

Leia e escreva arquivos com a API async fs.

process e env

Leia argumentos, variáveis de ambiente e códigos de saída.

Eventos e streams

Manipule dados em pedaços (chunks) e responda a eventos conforme eles ocorrem.

Módulos

Organize o código com import e export do ESM.

APIs e ferramentas

Construa APIs REST, servidores GraphQL, CLIs e workers de background.

Uma breve historia

JavaScript escapa do navegador

  1. 2009

    Lançamento do Node.js

    Ryan Dahl executa JavaScript no servidor com um modelo orientado a eventos.

    09
  2. 2011

    npm e Express

    Um gerenciador de pacotes e um framework web aceleram a adoção.

    11
  3. 2015

    Suporte de longo prazo

    Lançamentos LTS e uma fundação trazem estabilidade para uso em produção.

    15
  4. 2017

    async/await

    O código de servidor assíncrono torna-se muito mais fácil de ler.

    17
  5. Hoje

    Em todo lugar

    O runtime padrão para ferramentas de build, APIs, funções serverless e CLIs.

    Hoje

O guia completo

Fundamentos de Node.js: Tudo que voce precisa saber

Por que o Node.js é importante

O Node.js é um runtime que executa JavaScript fora do navegador. Lançado em 2009, ele utilizou o motor V8 do Chrome e o combinou com APIs para arquivos, rede e processos, permitindo que desenvolvedores utilizem a mesma linguagem em todo o stack.

Sua característica definidora é o I/O não bloqueante e orientado a eventos. Em vez de reservar uma thread por requisição e esperar enquanto o disco ou a rede respondem, o Node delega a operação lenta e continua com outras tarefas. Quando a operação termina, um callback é executado. Esse modelo o torna eficiente para APIs, apps em tempo real e ferramentas, sendo o mesmo event loop que você já conhece no JavaScript do navegador.

Executando JavaScript no servidor

O Node oferece a você um process global, um sistema de módulos e uma biblioteca padrão. Um servidor HTTP minimalista não precisa de dependências.

// server.js
import { createServer } from "node:http";

const server = createServer((req, res) => {
  if (req.url === "/health") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ status: "ok" }));
    return;
  }
  res.writeHead(404).end("Not found");
});

server.listen(process.env.PORT ?? 3000);

As importações integradas com o prefixo node: deixam claro quais módulos vêm do próprio Node. Este servidor processa as requisições conforme elas chegam e nunca bloqueia o I/O.

Módulos

O Node moderno utiliza ES modules, a mesma sintaxe de import e export utilizada no navegador.

// math.js
export function add(a, b) {
  return a + b;
}

// app.js
import { add } from "./math.js";

Defina "type": "module" no package.json para tratar arquivos .js como ES modules. O Node também ainda oferece suporte ao CommonJS (require e module.exports), que você encontrará em códigos mais antigos e em muitos pacotes. Novos projetos devem utilizar ES modules.

O sistema de arquivos

A API de sistema de arquivos do Node possui variantes assíncronas e síncronas. Use a API assíncrona em servidores.

// files.js
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";

const file = path.join(import.meta.dirname, "data.json");
const data = JSON.parse(await readFile(file, "utf8"));

await writeFile(file, JSON.stringify({ ...data, updated: Date.now() }, null, 2));

O módulo node:path lida com a junção de caminhos entre diferentes plataformas, e import.meta.dirname fornece o diretório do arquivo atual. Funções síncronas como readFileSync existem e são aceitáveis em scripts e códigos de inicialização, mas nunca dentro de um request handler.

Ambiente e configuração

A configuração deve ficar em variáveis de ambiente, não no código.

// env.js
const config = {
  port: Number(process.env.PORT ?? 3000),
  databaseUrl: process.env.DATABASE_URL,
  nodeEnv: process.env.NODE_ENV ?? "development",
};

Isso mantém segredos fora do repositório e permite que a mesma build seja executada em desenvolvimento, staging e produção. Carregue valores locais de um arquivo .env em desenvolvimento com uma ferramenta como dotenv ou o --env-file nativo do Node.js, e nunca faça commit desse arquivo.

Construindo APIs

A maioria dos apps Node.js utiliza um framework para lidar com roteamento, parsing e middleware. O Express é o mais utilizado; o Fastify é mais rápido e orientado a schemas.

// api.js
import express from "express";

const app = express();
app.use(express.json());

app.get("/api/users", async (req, res, next) => {
  try {
    const users = await db.users.findMany();
    res.json(users);
  } catch (error) {
    next(error);
  }
});

app.post("/api/users", async (req, res, next) => {
  try {
    const user = await db.users.create(req.body);
    res.status(201).json(user);
  } catch (error) {
    next(error);
  }
});

app.use((error, req, res, next) => {
  console.error(error);
  res.status(500).json({ message: "Something went wrong" });
});

app.listen(config.port);

Os handlers de rota são funções async, os erros são encaminhados para o middleware e um handler de erro final transforma exceções em respostas. Retorne status codes e headers significativos, e consulte Segurança Web para validar inputs e proteger sessões.

Streams, buffers e events

O Node manipula dados como streams para que payloads grandes não precisem caber inteiramente na memória.

// stream.js
import { createReadStream } from "node:fs";
import { createServer } from "node:http";

createServer((req, res) => {
  createReadStream("movie.mp4").pipe(res);
}).listen(3000);

Um buffer consiste em dados binários brutos, e um event emitter permite que objetos publiquem eventos nos quais outros se inscrevem. Streams e events são a engrenagem de baixo nível por trás de grande parte da biblioteca padrão do Node, e entendê-los explica como arquivos, sockets e HTTP funcionam internamente.

Erros e sinais de processo

Erros não tratados podem derrubar um processo Node.js, portanto, trate-os de forma deliberada.

// signals.js
process.on("SIGTERM", () => {
  server.close(() => process.exit(0));
});

process.on("unhandledRejection", (reason) => {
  console.error("Unhandled rejection", reason);
});

SIGTERM é enviado pela maioria das plataformas quando um container ou processo deve ser interrompido; tratá-lo permite que você finalize as requisições em andamento antes de encerrar a execução. Handlers globais servem como uma rede de segurança para logging, e não como um substituto para o tratamento de erros onde eles ocorrem.

Melhores práticas

  • Use APIs async nos request handlers e nunca bloqueie o event loop.
  • Mantenha as configurações em variáveis de ambiente.
  • Valide e sanitize todas as entradas no servidor.
  • Use ES modules e o prefixo node: para built-ins.
  • Centralize o tratamento de erros em middleware.
  • Faça stream de arquivos grandes em vez de lê-los na memória.
  • Trate SIGTERM para um graceful shutdown e exponha um endpoint de health.

Erros comuns

  • Usar readFileSync dentro de um request handler e travar o servidor.
  • Executar tarefas pesadas de CPU na main thread.
  • Commitar arquivos .env ou deixar secrets hardcoded.
  • Confiar em inputs do cliente sem validação.
  • Ignorar unhandled promise rejections.
  • Ler arquivos grandes inteiramente na memória em vez de usar streaming.

Próximos passos

O Node.js completa a visão full-stack. Gerencie dependências com npm, entenda o protocolo HTTP que seu servidor utiliza, proteja-o com Web Security e empacote-o com Docker. Depois, construa uma pequena API com duas rotas, uma chamada de banco de dados e um manipulador de erros, e faça o deploy.

Lendo arquivos

Use a API async para que o event loop permaneça livre. Chamadas bloqueantes travam todas as outras requisições enquanto aguardam.

Preferir
import { readFile } from "node:fs/promises";

const data = await readFile("config.json", "utf8");
const config = JSON.parse(data);
Evitar
import { readFileSync } from "node:fs";

// blocks the whole server
// while the disk responds
const data = readFileSync("config.json", "utf8");

Configuração

Leia segredos e valores específicos do ambiente a partir de variáveis de ambiente para que a mesma imagem rode em qualquer ambiente.

Preferir
const port = process.env.PORT ?? 3000;
const dbUrl = process.env.DATABASE_URL;
Evitar
const port = 3000;
const dbUrl = "postgres://localhost/prod";
// committed credentials

Perguntas frequentes

Perguntas frequentes

Keep learning

Related topics from the roadmap.

$ comecar a aprender

Pronto para aprender Node.js Basics?

Nosso tutorial interativo te guia por Node.js Basics passo a passo — com quizzes e codigo real que voce pode executar no navegador.