Creando nuestro primer servidor HTTP y usando watch
En esta clase damos el primer paso real en el desarrollo backend con Node.js: crear un servidor HTTP desde cero, sin frameworks y usando únicamente módulos nativos.
Entender cómo funciona la comunicación básica entre cliente y servidor es fundamental antes de pasar a herramientas de mayor nivel como Express.
El módulo nativo node:http
Node.js trae de serie todo lo necesario para montar un servidor. No necesitas instalar nada externo para empezar, ya que Node:
- Tiene módulos nativos para comunicaciones.
- Tiene acceso directo a la red.
- Puede levantar servidores HTTP de forma eficiente.
Para empezar, usaremos el módulo node:http, que es la base de prácticamente todos los frameworks web en el ecosistema de Node.js.
Crear un servidor HTTP básico
Un servidor HTTP en Node.js se basa en un ciclo de petición (Request) y respuesta (Response).
Para crear uno, utilizamos el método createServer. Este método recibe una función (callback) que se ejecutará cada vez que el servidor reciba una petición.
import http from 'node:http'
const server = http.createServer((req, res) => {
console.log('Petición recibida')
res.end('Hola desde tu primer servidor de Node.js!')
})
Request y Response
La función que pasamos a createServer recibe dos objetos fundamentales:
req(Request): Contiene toda la información de la petición que hace el cliente (la URL, el método HTTP, las cabeceras, etc.).res(Response): Es el objeto que usamos para enviarle la respuesta al cliente.
Escuchar en un puerto
Una vez definido el servidor, tenemos que decirle que “escuche” en un puerto específico de nuestra máquina para poder recibir tráfico.
const DESIRED_PORT = 3000
server.listen(DESIRED_PORT, () => {
console.log(`Servidor escuchando en el puerto http://localhost:${DESIRED_PORT}`)
})
El ciclo de vida de la respuesta
Un error común al empezar es olvidar finalizar la respuesta. Si el servidor recibe la petición pero nunca llama a res.end(), el navegador se quedará cargando indefinidamente (en estado pending) esperando a que el servidor cierre la conexión.
Siempre debemos:
- Escribir el contenido (opcionalmente con
res.write()). - Finalizar la respuesta con
res.end().
Cabeceras y Codificación (UTF-8)
Si intentas enviar caracteres especiales (como acentos o emojis) y no configuras correctamente el servidor, el navegador podría mostrarlos mal. Esto sucede porque el navegador no sabe qué tipo de contenido está recibiendo ni qué codificación usa.
Podemos solucionar esto enviando una cabecera HTTP:
const server = http.createServer((req, res) => {
// Configuramos la cabecera con el código de estado 200 (OK)
res.setHeader('Content-Type', 'text/plain; charset=utf-8')
res.end('¡Hola Mundo! 🚀 Aquí tienes un servidor con tildes.')
})
Tip: Puedes inspeccionar estas cabeceras en las Herramientas de Desarrollo de tu navegador (F12), en la pestaña Network, seleccionando la petición a
localhost.
Mejorando el desarrollo con el modo watch
Por defecto, cuando haces un cambio en tu archivo de Node.js, tienes que:
- Parar el proceso actual (
Ctrl + C). - Volver a ejecutar
node servidor.js.
Esto es muy tedioso. Afortunadamente, las versiones recientes de Node.js (v18.11+) incluyen un modo watch nativo.
Para usarlo, simplemente añade el flag --watch:
node --watch servidor.js
Ahora, cada vez que guardes el archivo, Node.js reiniciará el servidor automáticamente. ¡Mucho más productivo!
Por qué empezar sin frameworks
Aunque en el mundo real usaremos Express, Fastify o NestJS, empezar con el módulo http nativo te permite entender:
- Qué es realmente una petición.
- Cómo funcionan los flujos de datos (streams).
- La importancia de las cabeceras.
- El ciclo de vida de una conexión.
Una vez dominas esto, verás que Express no es “magia”, sino una capa de utilidades sobre lo que acabas de aprender.
Resumen de la clase
- ✅ Creamos un servidor con
node:http. - ✅ Entendimos la diferencia entre
req(petición) yres(respuesta). - ✅ Aprendimos a configurar el puerto con
server.listen. - ✅ Vimos la importancia de las cabeceras para la codificación UTF-8.
- ✅ Usamos el flag
--watchpara un desarrollo más rápido.
¡Ya tienes tu primer servidor funcionando! En la siguiente clase empezaremos a gestionar diferentes rutas.