Objetivos de aprendizaje
Después de leer este artículo podrás:
- Preparar un proyecto Node.js para ejecutarse fuera de tu máquina
- Escribir un servidor que lee el puerto del entorno y se cierra con seguridad
- Verificar el deploy y corregir los errores más comunes
En esta página
- ¿Qué necesitas antes de hospedar?
- ¿Cómo preparar el proyecto?
- ¿Cómo escribir un servidor listo para producción?
- ¿Cómo manejar las variables de entorno y los secretos?
- ¿Cómo subir el código e iniciar el proceso?
- ¿Cómo verificar que funcionó?
- ¿Cuáles son los errores más comunes?
- Cómo hacerlo en Square Cloud
- Preguntas frecuentes
Una aplicación Node.js funciona en tu máquina porque ahí están el Node correcto, las dependencias instaladas y las variables que configuraste. Hospedar es reproducir ese entorno en un servidor que está encendido todo el tiempo y al que otras personas pueden acceder.
El camino es el mismo para una API, un sitio con servidor o un bot: preparar el proyecto, subir el código, instalar las dependencias e iniciar el proceso. Esta guía usa una API con Express como ejemplo, pero los pasos valen para cualquier app Node.js. Para la visión general, mira qué es el deploy.
¿Qué necesitas antes de hospedar?#
- Una versión de Node definida. Elige una versión LTS y usa la misma en local y en producción.
- Un
package.jsoncompleto, con las dependencias y un script de inicio. - Un
package-lock.jsonincluido en el repositorio, para que la instalación sea idéntica en cualquier máquina. - Un lugar donde ejecutarla: un VPS, un contenedor o una plataforma de hospedaje. La diferencia entre ellos está en VPS vs plataforma en la nube.
¿Qué LTS elegir? Para un proyecto nuevo, usa la versión LTS activa de Node.js, siempre que tus dependencias la soporten, y declara la versión en el package.json. El calendario oficial muestra qué versión está en esa fase y hasta cuándo recibe correcciones cada una.
¿Cómo preparar el proyecto?#
Crea la estructura mínima:
mkdir mi-api && cd mi-api
npm init -y
npm install expressAjusta el package.json para módulos ES, con la versión de Node y los scripts:
{
"name": "mi-api",
"version": "1.0.0",
"type": "module",
"main": "index.js",
"engines": { "node": ">=24" },
"scripts": {
"start": "node index.js",
"dev": "node --watch --env-file-if-exists=.env index.js"
},
"dependencies": {
"express": "^5.0.0"
}
}El campo engines documenta la versión esperada, y el script start es el comando que ejecutará el servidor. dev usa dos flags nativas de Node: --watch reinicia el proceso cuando cambia un archivo, y --env-file-if-exists carga las variables de un archivo .env (sin error si no existe), sin necesidad del paquete dotenv.
¿Cómo escribir un servidor listo para producción?#
Un servidor de pruebas se vuelve un servidor de producción cuando lee el puerto del entorno, mantiene los secretos fuera del código y maneja la señal de cierre.
// index.js
import express from "express";
const app = express();
const port = Number(process.env.PORT) || 3000;
app.get("/", (req, res) => {
res.send("¡Hola, mundo!");
});
app.get("/health", (req, res) => {
res.json({ status: "ok" });
});
const server = app.listen(port, "0.0.0.0", () => {
console.log(`Servidor escuchando en el puerto ${port}`);
});
// Al recibir SIGTERM (reinicio o despliegue), deja de aceptar
// conexiones nuevas y termina las que están en curso.
process.on("SIGTERM", () => {
server.close(() => process.exit(0));
});Por qué importa cada parte:
process.env.PORT: la plataforma o el servidor decide el puerto y lo informa por variable. Fijar3000solo funciona en tu máquina. El|| 3000es el valor para desarrollo.- Ruta
/health: te da a ti (y a monitores externos) una dirección ligera para comprobar que la app responde. SIGTERM: es la señal que el sistema envía para pedir que el proceso termine. Cuando registras un listener, Node deja de salir al instante (su comportamiento por defecto), así que debes terminar el proceso explícitamente, como en el ejemplo.
Prueba en local con npm run dev y abre http://localhost:3000/health.
¿Cómo manejar las variables de entorno y los secretos?#
Los tokens, las contraseñas de base de datos y las claves de API van en variables de entorno, nunca en el repositorio. Léelas con process.env.NOMBRE. En local, usa un archivo .env y agrégalo al .gitignore; en producción, registra cada variable en el panel de tu proveedor o en el proceso del servidor. La guía qué son las variables de entorno detalla el patrón.
Falla pronto cuando falte una variable obligatoria. En lugar de un error oscuro más adelante, recibes un mensaje claro al arrancar:
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL no está definida");
}¿Cómo subir el código e iniciar el proceso?#
El flujo general, en cualquier hospedaje:
- Sube el código sin
node_modulesy sin el.env(usa un.gitignore). - En el servidor, instala las dependencias exactas del lockfile:
npm ci --omit=dev. - Define las variables de entorno, incluido
NODE_ENV=production. - Inicia con
npm start(onode index.js). - Mantén el proceso vivo: en un VPS, con un supervisor como systemd o PM2; en contenedores y plataformas, con su política de reinicio. Mira también cómo empaquetar con Docker.
Si tu app es una API, repasa el checklist de producción para APIs antes de abrirla al público.
¿Cómo verificar que funcionó?#
Después del deploy, confirma en tres pasos:
- Logs: la línea "Servidor escuchando en el puerto" debe aparecer sin errores a continuación.
- Petición: llama a
/healthdesde la dirección pública y espera{"status":"ok"}. - Reinicio: reinicia la app y confirma que vuelve sola.
¿Cuáles son los errores más comunes?#
Error: listen EADDRINUSE: address already in use: otro proceso ya ocupa el puerto. Detén la instancia anterior o cambia el puerto.Cannot find module 'express': las dependencias no se instalaron, o el paquete está endevDependenciesy instalaste con--omit=dev. Muévelo adependencies.SyntaxError: Cannot use import statement outside a module: falta"type": "module"en elpackage.json, o usasimporten un archivo tratado como CommonJS.- La app arranca, pero el sitio no abre: el servidor escucha en un puerto fijo en lugar de
process.env.PORT, o solo enlocalhost. En contenedores, escucha en0.0.0.0. - Funciona en local, falla en producción: versión de Node distinta, variable de entorno ausente o memoria insuficiente. Compara qué cambió entre los entornos.
Cómo hacerlo en Square Cloud#
El flujo de esta guía cambia poco en Square Cloud. Subes el proyecto como ZIP en el panel, con la CLI, desde GitHub (un push dispara el deploy) o con la extensión de VS Code, y el formulario de deploy detecta index.js como archivo principal. El archivo squarecloud.app es opcional: el panel lo genera en el deploy. Si prefieres el script del package.json, el campo de comando de inicio acepta cualquier comando de shell, como npm start o npm run migrate && npm start.
La instalación sigue dos reglas que explican errores de la lista anterior. La plataforma solo ejecuta npm install cuando no existe node_modules, así que sube el proyecto sin esa carpeta. Además, instala con NODE_ENV=production: lo que esté en devDependencies queda fuera, y el resultado es el Cannot find module. No hay paso de build; para compilar, usa un CI externo como GitHub Actions o pon el build en el comando de inicio. El runtime de TypeScript ejecuta tu código sin una compilación previa.
El puerto viene de la variable PORT, que define la plataforma, y el servidor escucha en 0.0.0.0, como en el ejemplo. Las variables de entorno se definen por aplicación en el panel (que importa un .env), ya existen durante la instalación y valen desde el siguiente reinicio, sin rebuild. El contenedor está siempre encendido, y el reinicio automático, activado por defecto en el deploy desde el panel, levanta de nuevo un proceso que terminó con error, así que PM2 sobra. Quedarse sin memoria detiene la aplicación hasta que aumentes su RAM. La salida de npm install y la línea "Servidor escuchando en el puerto" aparecen en los logs en tiempo real.
Cada aplicación web usa al menos 512 MB de la RAM del plan, y el Hobby empieza en R$12,49 al mes con 1 GB. Node.js es uno de varios runtimes, junto a Python, Go y Java: consulta los runtimes disponibles hoy en Runtimes y los planes en hosting de APIs.
Hosting de APIs
APIs en contenedores siempre encendidos, sin cold start
Preguntas frecuentes
¿Qué versión de Node.js debo usar en producción?
Usa la versión LTS activa de Node.js, que recibe correcciones de seguridad durante más tiempo. Consulta en el calendario oficial de Node.js cuál es antes de fijar la versión en tu proyecto.
¿Necesito PM2 para mantener la aplicación en línea?
Depende del entorno. En un servidor que administras tú, un supervisor de procesos reinicia la app si se cae. En plataformas que ya reinician el proceso por su cuenta, PM2 suele ser innecesario.
¿Debo subir la carpeta node_modules?
Normalmente no. Sube package.json y package-lock.json y deja que el entorno instale las dependencias con npm ci. La carpeta node_modules puede ser enorme y depende del sistema operativo.
¿Puedo hospedar una aplicación Node.js escrita en TypeScript?
Sí. Puedes compilar a JavaScript antes del deploy o usar una plataforma que ejecute TypeScript directamente. Ejecutar el código compilado suele ser la opción más predecible.
Más en APIs
Ver los 15 artículos- Cómo hospedar una APIHospedar una API es ejecutar su servidor HTTP las 24 horas en una dirección pública con HTTPS. Guía paso a paso con Node.js y Python, pruebas y errores comunes.
- Cómo hospedar una app o script de PythonPara hospedar una app o script de Python, fija la versión, aísla las dependencias en un venv, lee los secretos del entorno y maneja SIGTERM. Guía paso a paso.
- Qué es un cron job y cómo programar tareasUn cron job es una tarea que corre sola en horarios definidos por una expresión de 5 campos. Mira sintaxis, ejemplos, errores comunes y cómo programar en Node.js.
- Checklist para llevar tu API a producciónChecklist para llevar una API a producción: variables de entorno, health check, apagado limpio, errores estándar, autenticación, rate limit, CORS y logs.