Nivel inicial10 min de lectura · Publicado el

Instalación de Express.js y primer Hola mundo

Instalación de Express.js: app.get manda cada petición a su ruta; / responde Hello World! y /prueba, Prueba!!!, en el puerto 3000. Una ruta, una respuestarubentejera.com /Hello World!/pruebaPrueba!!!app.getpuerto 3000
Como la recepción de un hotel: cada petición llega al mostrador y app.get la manda a su puerta. La ruta / responde «Hello World!» y /prueba, «Prueba!!!». El hotel está en el puerto 3000.

Express es una librería para Node.js que facilita crear servidores web: tú dices qué responder en cada dirección y Express se encarga del resto.

Funciona como la recepción de un hotel: cada petición llega a recepción y Express la manda al sitio correcto según lo que pide (la ruta /, la ruta /prueba…).

Instalación

Necesitas Node.js 18 o superior: Express 5 lo requiere. Si no lo tienes, mira cómo instalar Node.js en Ubuntu.

1. Crea la carpeta del proyecto

mkdir myapp
cd myapp

2. Crea el package.json

package.json es la ficha del proyecto: su nombre, su versión y las librerías de las que depende.

npm init

npm te pregunta varios datos. Puedes pulsar Intro para aceptar los valores por defecto, salvo en este:

entry point: (index.js)

Escribe app.js (o el nombre que quieras para el fichero principal). Si prefieres index.js, pulsa Intro.

Si no quieres responder preguntas, npm init -y acepta todos los valores por defecto de golpe.

3. Instala Express

npm install express

Desde npm 5, npm install ya guarda la librería en las dependencias de package.json, así que la opción --save del artículo original sobra. Si quieres instalar Express de forma temporal, sin apuntarlo en package.json, usa --no-save:

npm install express --no-save

Hola mundo

En la carpeta myapp, crea un fichero app.js con este código:

const express = require('express');

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, (error) => {
  if (error) throw error;
  console.log(`Example app listening on port ${port}`);
});

Qué hace cada parte:

Línea Qué hace
express() Crea la aplicación
app.get('/', …) Cuando alguien pide la dirección /, responde con «Hello World!»
app.listen(port, …) Arranca el servidor en el puerto 3000
if (error) throw error En Express 5, si el puerto está ocupado, el error llega aquí

Arranca el servidor:

node app.js

Abre http://localhost:3000 en el navegador y verás Hello World!.

Añadir otra ruta

Cada ruta es un app.get más. Añade esta antes de app.listen:

app.get('/prueba', (req, res) => {
  res.send('Prueba!!!');
});

Para el servidor con Ctrl + C, arráncalo otra vez y abre http://localhost:3000/prueba: verás Prueba!!!.

Para no tener que reiniciarlo a mano cada vez, arráncalo con node --watch app.js: lo tienes en reinicio automático del servidor Node.

Una ruta, una respuesta. Express no es más que eso al principio.

Compruébalo con un test

Abrir el navegador cada vez no escala: un test pide las rutas por ti. Para que el test pueda arrancar el servidor a su manera, app.js tiene que exportar la aplicación y escuchar en el puerto solo cuando lo ejecutas directamente. Así queda completo, con las dos rutas:

const express = require('express');

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.get('/prueba', (req, res) => {
  res.send('Prueba!!!');
});

if (require.main === module) {
  app.listen(port, (error) => {
    if (error) throw error;
    console.log(`Example app listening on port ${port}`);
  });
}

module.exports = app;

require.main === module es verdadero cuando arrancas con node app.js y falso cuando otro fichero hace require('./app'). Ahora crea app.test.js con el ejecutor de tests que trae Node, node:test, sin instalar nada:

const test = require('node:test');
const assert = require('node:assert');
const app = require('./app');

test('las dos rutas responden', async (t) => {
  const server = app.listen(0);
  t.after(() => server.close());
  const base = `http://localhost:${server.address().port}`;

  const portada = await fetch(`${base}/`);
  assert.strictEqual(portada.status, 200);
  assert.strictEqual(await portada.text(), 'Hello World!');

  const prueba = await fetch(`${base}/prueba`);
  assert.strictEqual(await prueba.text(), 'Prueba!!!');

  const otra = await fetch(`${base}/no-existe`);
  assert.strictEqual(otra.status, 404);
});

app.listen(0) pide al sistema un puerto libre cualquiera, así que el test funciona aunque tengas el servidor arrancado en el 3000.

node --test
✔ las dos rutas responden (46.727948ms)
ℹ tests 1
ℹ pass 1
ℹ fail 0

Express Generator o a mano

Express tiene un generador que crea un proyecto con carpetas, vistas y rutas de ejemplo:

npx express-generator --view=ejs mi-app

Sigue apareciendo en la documentación de Express 5, pero conviene saber lo que hace hoy. La última versión publicada, la 4.16.1, es de mayo de 2019, y el proyecto que genera usa Express 4, no 5:

"dependencies": {
  "cookie-parser": "~1.4.4",
  "debug": "~2.6.9",
  "ejs": "~2.6.1",
  "express": "~4.16.1",
  "http-errors": "~1.6.3",
  "morgan": "~1.9.1"
}

Al instalar esas dependencias, npm avisa de vulnerabilidades conocidas en ellas:

10 vulnerabilities (4 low, 1 moderate, 4 high, 1 critical)

El repositorio del generador sigue abierto y recibe cambios de mantenimiento en su configuración, pero no versiones nuevas. Si empiezas un proyecto hoy, la opción más sencilla y actual es la de este artículo: npm install express y escribir tú app.js. Usa el generador solo para ver una forma de organizar carpetas, sabiendo que tendrás que actualizar Express y sus dependencias a mano.

A mano Express Generator
Versión de Express La última (5.3.0) 4.16
Ficheros Los que tú crees Carpetas routes, views, public y bin/www
Vulnerabilidades al instalar 0 10, según npm audit

Errores frecuentes

1. Cannot find module 'express'. Has escrito app.js pero no has instalado Express en esa carpeta, o lo arrancas desde otra:

Error: Cannot find module 'express'
Require stack:
- /tmp/sin/app.js

Ejecuta npm install express en la carpeta donde está package.json y arranca desde ahí.

2. EADDRINUSE: el puerto está ocupado. Otro programa usa el 3000, a menudo una ejecución anterior que se quedó abierta. En Express 5, el error llega al callback de app.listen y el throw error lo muestra. Con el app.js completo del apartado anterior:

/tmp/myapp/app.js:16
    if (error) throw error;
               ^

Error: listen EADDRINUSE: address already in use :::3000

Cierra la otra ejecución o cambia el puerto. Si no sabes qué programa es, mira cómo matar un proceso en Linux.

3. require is not defined in ES module scope. Tu package.json tiene "type": "module", así que Node trata los .js como módulos ES, que no tienen require:

ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and '/tmp/esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

npm init -y con npm 11 escribe "type": "commonjs", así que con el ejemplo de este artículo no te pasará. Si prefieres módulos ES, cambia la primera línea por import express from 'express';. Las diferencias entre las dos formas están en exportar e importar funciones en JavaScript.

4. Una ruta comodín copiada de un tutorial de Express 4. Express 5 cambió la sintaxis de las rutas, y app.get('*', …) ya no vale. El servidor ni arranca:

PathError [TypeError]: Missing parameter name at index 1: *; visit https://git.new/pathToRegexpError for info
  originalPath: '*'

En Express 5, el comodín necesita un nombre. Si pones esta ruta la última, recoge todo lo que no ha encajado antes:

app.get('/*ruta', (req, res) => {
  res.send(`No hay nada en /${req.params.ruta.join('/')}`);
});

Con esa ruta, pedir /a/b responde No hay nada en /a/b. Fíjate en que req.params.ruta es un array con cada trozo de la dirección (['a', 'b']), no un texto. /*ruta no recoge la portada, /; la guía de migración explica que, para incluirla, se escribe /{*ruta}.

Cuándo no usar Express

  • Si solo quieres servir ficheros estáticos (una web en HTML, sin lógica en el servidor), no necesitas un servidor propio: cualquier alojamiento de páginas estáticas lo hace.
  • Si necesitas una estructura completa desde el principio (inyección de dependencias, validación, módulos), Express no la impone: te deja decidir. Es una ventaja para aprender y para servicios pequeños; en un proyecto grande, tendrás que acordar esa estructura con tu equipo.

Ejercicio de cinco minutos

  1. Añade al test una petición a /saludo/Ana que espere la respuesta Hola, Ana. Ejecuta node --test y comprueba que falla.
  2. Haz que pase con una ruta app.get('/saludo/:nombre', …) que responda con req.params.nombre.
  3. Arranca los tests en modo vigilancia con node --test --watch y cambia el saludo: verás el test en rojo nada más guardar.

Qué ha cambiado desde la primera versión

  • El ejemplo usa const y funciones flecha en lugar de var y function. Hace lo mismo, pero es la forma habitual de escribir JavaScript hoy.
  • Express 5 es la versión actual y pide Node.js 18 o superior.
  • npm install express ya guarda la dependencia sin --save.

Fuentes

  • Express, Instalación y Hola mundo: requisito de Node.js 18 o superior y opción --no-save. La versión original de este artículo seguía la guía en español de Express 4.
  • Express, Express application generator, en la documentación de la versión 5.x: npx express-generator y sus opciones.
  • Express, Moving to Express 5: el comodín necesita nombre (/*splat) y /{*splat} incluye también la raíz.
  • express en npm: 5.3.0 es la versión latest, comprobada con npm view express version; la rama 4 sigue publicándose con la etiqueta latest-4 (4.22.3).
  • express-generator en npm: 4.16.1, publicada el 3 de mayo de 2019, sin versiones posteriores. Repositorio: no está archivado y sus últimos cambios son de mantenimiento.

Ejecutado el 12 de noviembre de 2026 en Docker con las imágenes oficiales node:24 (Node 24.22.3 y npm 11.19.1) y node:26 (Node 26.13.1 y npm 11.20.0), con Express 5.3.0 y el mismo resultado en las dos: npm init -y (que escribe "type": "commonjs"), npm install express (que añadió "express": "^5.3.0" a dependencies), el servidor con las rutas / y /prueba comprobadas con curl, el test con node --test, express-generator 4.16.1 con su npm install, y los cuatro errores. La versión con import se ejecutó solo con Node 24.22.3.