Lección 2 de 12 · Lectura y práctica
Estructura de proyecto, env vars y configuracion
Estructura de proyecto, variables de entorno y configuración Una API que funciona en tu máquina pero falla en producción casi siempre tiene un problema de configuración. La regla de oro del enfoque Twelve-Factor es separar la.
Del concepto a la práctica
Taller de esta lección
Separar app de server permite probar rutas sin abrir un puerto y hace visible qué configuración es obligatoria. La validación debe ocurrir al arrancar, no después de recibir la primera solicitud.
Ejemplo resuelto
const required = (name) => {
const value = process.env[name];
if (!value) throw new Error(`Falta ${name}`);
return value;
};
const portText = process.env.PORT ?? "3000";
const port = Number(portText);
if (!/^\d+$/.test(portText) || !Number.isInteger(port) || port < 1 || port > 65535) {
throw new Error("PORT inválido");
}
export const config = {
port,
databaseUrl: required('DATABASE_URL')
};Con PORT=4100 y una URL presente, el puerto resulta 4100; sin DATABASE_URL, el proceso falla con un mensaje identificable.
Usa package.json con type:module para este export, o convierte coherentemente a CommonJS. Tener .env.example no carga el entorno: usa el mecanismo de carga declarado por tu runtime. Prueba PORT=abc, PORT=0 y PORT=65536: todos deben fallar antes de escuchar. Nunca incluyas la URL con contraseña en logs; un valor requerido presente tampoco demuestra que la base responda.
Pruébalo
Crea
src/config.jsysrc/server.jsseparados.Define
PORTyDATABASE_URLsolo en el entorno local.Ejecuta una vez con ambas variables y otra sin la segunda.
Error frecuente: usar Number(process.env.PORT) sin comprobar NaN. Corrige aceptando un valor predeterminado o rechazando explícitamente un puerto no numérico.
Ejercicio: documenta PORT y DATABASE_URL en .env.example, sin valores secretos.
Comprueba tu resultado
otra persona puede identificar ambas variables y el arranque incompleto falla antes de escuchar.

Mapa de prácticaEl navegador envía una solicitud a la API. El servidor valida la operación y consulta los datos; después devuelve una respuesta que el navegador puede mostrar. La base de datos se comunica con el servidor y no directamente con el navegador.
Ver la infografía en tamaño completo ↗Estructura de proyecto, variables de entorno y configuración
Una API que funciona en tu máquina pero falla en producción casi siempre tiene un problema de configuración. La regla de oro del enfoque Twelve-Factor es separar la configuración del código: lo que cambia entre tu portátil, el servidor de pruebas y producción (puertos, URLs de base de datos, claves) vive en el entorno, nunca dentro de los archivos versionados en Git.
Una estructura sencilla y escalable
mi-api/
src/
config.js # lee y valida process.env
app.js # crea la app Express (sin escuchar)
server.js # arranca y escucha en el puerto
routes/
middleware/
db/
.env # NUNCA se sube a Git
.env.example # plantilla que sí se versiona
.gitignore
Separar app.js (la configuración de Express) de server.js (el listen) te permite importar la app en tus tests sin abrir un puerto real.
Centraliza y valida la configuración
// src/config.js
import 'dotenv/config';
function required(name) {
const value = process.env[name];
if (!value) throw new Error(`Falta la variable de entorno ${name}`);
return value;
}
export const config = {
port: Number(process.env.PORT ?? 3000),
databaseUrl: required('DATABASE_URL'),
nodeEnv: process.env.NODE_ENV ?? 'development',
};
Atención
Añade .env a tu .gitignore el primer día. Subir credenciales a un repositorio, aunque sea privado, es la fuga de secretos más común y la más cara de revertir.
Falla rápido, no a medias
Si falta DATABASE_URL, es mejor que la app no arranque a que lance un error críptico en la primera consulta de un usuario real. Validar al inicio convierte un fallo silencioso en un error claro y temprano.
¿Qué archivo debe versionarse en Git para documentar las variables sin filtrar secretos?
Ejercicio práctico
Objetivo: montar una configuración robusta que falle rápido.
- Crea
config.jscon la funciónrequired()de arriba y al menosPORTyDATABASE_URL. - Crea un
.env.exampley añade.enval.gitignore. - Añade scripts a
package.json:"dev": "node --watch src/server.js"y"start": "node src/server.js". - Arranca sin
DATABASE_URLy comprueba que el proceso muere con un mensaje claro.
Entregable: tu config.js, tu .env.example y una captura del error al faltar una variable.
Para recordar
- La configuración va en el entorno, no en el código.
.envnunca se sube;.env.examplesí.- Valida todas las variables al arrancar y falla rápido con un mensaje útil.
Sigue con Node.js y APIs con Express
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.