Guía práctica de CI/CD para Next.js: pruebas y despliegue automáticos con GitHub Actions

Mirando los logs que se desplazan en la terminal, los dedos teclean mecánicamente git pull && npm install && npm run build && pm2 restart. Tercer despliegue del día: por la mañana arreglé un bug pequeño, al mediodía optimicé un endpoint y ahora toqué un poco el estilo. Tres servidores, hay que repetir la operación en cada uno.
Al terminar con el último, el reloj marca las siete.
De camino a casa esa noche pensaba: tiene que haber una forma mejor. No quiero repetir estas operaciones en el servidor cada vez que cambio código, ni preocuparme de que algún servidor se quede sin reiniciar y rompa producción. Tampoco suelo acordarme de ejecutar las pruebas: termino de codificar y quiero desplegar ya, y luego descubro bugs y hay que empezar otra vez.
Cuando conocí CI/CD y GitHub Actions, el flujo de trabajo cambió por completo. Ahora solo hago push a GitHub y el resto —pruebas, build, despliegue— se hace solo. En el tiempo de un café, la nueva versión ya está online.
Si el despliegue manual también te está castigando, en lo que sigue comparto cómo montar un pipeline automatizado para Next.js con GitHub Actions. Desde la configuración más básica hasta un caso completo, incluyendo los fallos que me encontré y cómo los resolví.
Por qué necesitas CI/CD
Los dolores del despliegue manual
Cuando empecé con proyectos Next.js, el flujo era: codificar en local, probar un poco, SSH al servidor, git pull, npm install, npm run build y pm2 restart. En el mejor caso, unos quince minutos.
Pero a menudo no va bien.
Una vez desplegué en tres servidores: los dos primeros bien, el tercero se cortó el SSH y no me di cuenta. Al día siguiente los usuarios decían que a veces la web iba bien y a veces veían una versión antigua: el balanceador repartía tráfico al servidor sin actualizar. Otra vez, emocionado tras un cambio, desplegué sin ejecutar pruebas. En producción apareció un bug grave y tuve que hacer rollback de urgencia.
Peor aún: el problema del build en varios servidores. Cada build de Next.js genera un build ID nuevo; si cada servidor construye por su cuenta, los ID no coinciden. Con balanceo, Next.js detecta el cambio de ID y fuerza un hard refresh recargando todos los recursos. La experiencia de usuario, fatal.
Qué resuelve CI/CD
En resumen, CI/CD automatiza procesos repetitivos y propensos a error.
CI (integración continua) se encarga de las pruebas. Cada push ejecuta tests, comprobación de tipos y lint. ¿Fallan? Ese commit no se despliega: error y a corregir. Así evitas subir código roto a producción.
CD (despliegue continuo) se encarga del build y del despliegue. ¿Pasaron las pruebas? Build automático y, al terminar, despliegue al servidor. Sin mover un dedo.
En la práctica: codifico en local → push a GitHub → pruebas → build → despliegue. De push a producción, unos cinco minutos, sin vigilancia. Puedo ir por un café y la nueva versión ya está online.
Otra ventaja: trazabilidad. Cada despliegue deja logs completos: qué commit lo disparó, resultado de pruebas, a qué servidor fue. Si algo falla, localizas rápido en lugar de ir a ciegas.
Configuración básica de GitHub Actions
Cómo funciona
Al principio, workflow, job y step me mareaban. En realidad es sencillo:
Workflow es el flujo automatizado completo; por ejemplo «pruebas + build + despliegue». Se define en un YAML en .github/workflows.
Job es una tarea independiente dentro del workflow. Puedes tener un job de «pruebas» y otro de «despliegue». Los jobs pueden ejecutarse en paralelo o con dependencias en serie.
Step es la acción concreta dentro de un job: checkout, instalar dependencias, ejecutar pruebas, etc.
Los disparadores son flexibles: push a main, solo en pull request, o cron diario a las 3 de la madrugada.
Tu primer workflow
Crea la carpeta .github/workflows en la raíz y un archivo ci-cd.yml. La configuración mínima:
name: CI/CD Pipeline
# Disparador: push a la rama main
on:
push:
branches: [main]
jobs:
build:
# Ejecutar en Ubuntu latest
runs-on: ubuntu-latest
steps:
# Paso 1: checkout del código
- uses: actions/checkout@v4
# Paso 2: configurar Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
# Paso 3: instalar dependencias
- name: Install dependencies
run: npm ci
# Paso 4: build del proyecto
- name: Build
run: npm run build
Significa: en cada push a main, en Ubuntu se hace checkout, Node.js, dependencias y build.
Tras subir el archivo a GitHub, en la pestaña Actions verás la ejecución. La primera vez que ves el check verde, da gusto.
Secrets para información sensible
Para desplegar en un servidor necesitas IP, clave SSH, tokens API, etc. No los escribas en el YAML ni los subas al repo.
Usa GitHub Secrets: Settings → Secrets and variables → Actions → New repository secret. Por ejemplo SERVER_HOST con la IP del servidor.
En el workflow referéncialo con ${{ secrets.SERVER_HOST }}. GitHub sustituye el valor y lo enmascara en los logs.
Montar el flujo de pruebas automáticas
Configuración del entorno de pruebas
Mi regla: automatiza todo lo que puedas. Incluyo ESLint, comprobación de tipos TypeScript y pruebas unitarias con Jest; eso filtra la mayoría de problemas.
Job de pruebas completo:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm' # cache de npm para acelerar builds siguientes
- name: Install dependencies
run: npm ci
- name: Lint check
run: npm run lint
- name: Type check
run: npm run type-check
- name: Run tests
run: npm run test -- --coverage
Truco: cache: 'npm' cachea node_modules; en la segunda ejecución no descargas todo de nuevo y ahorras minutos.
Cómo acelerar las pruebas
Al principio tardaba más de diez minutos por ejecución. Tras optimizar, unos tres.
Primera técnica: caché. Además de npm, cachea el build de Next.js:
- name: Cache Next.js build
uses: actions/cache@v3
with:
path: |
~/.npm
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
Next.js no reconstruye todas las páginas cada vez.
Segunda técnica: paralelismo. Si las pruebas son independientes, divide en varios jobs:
jobs:
lint:
runs-on: ubuntu-latest
steps: [...] # solo lint
test:
runs-on: ubuntu-latest
steps: [...] # solo unit tests
type-check:
runs-on: ubuntu-latest
steps: [...] # solo type check
Los tres arrancan a la vez; el tiempo total es el del job más lento, no la suma.
Errores que me encontré
Configuré pruebas que en local iban bien y en GitHub Actions fallaban. Tras depurar: al hacer checkout de un PR, Actions fusiona la rama del PR con la destino y crea un commit temporal que no existe en local, lo que puede romper cosas.
Solución al hacer checkout:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }} # código original de la rama del PR
Otro problema: timeout en E2E lentos. Sube el límite del job:
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15 # por defecto son 6 minutos
Configurar el despliegue automático
Desplegar en Vercel: la opción más simple
Si el proyecto está en Vercel, casi no configuras nada. Vercel e GitHub van integrados: conectas el repo y cada push despliega solo.
Para más control —por ejemplo desplegar solo si pasan las pruebas— usa la action oficial:
jobs:
deploy:
runs-on: ubuntu-latest
needs: test # esperar al job de pruebas
if: github.ref == 'refs/heads/main' # solo en main
steps:
- uses: actions/checkout@v4
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: '--prod' # entorno de producción
Genera un token en Vercel, obtén org ID y project ID en ajustes del proyecto y añádelos a GitHub Secrets.
Vercel también crea preview por PR: enlace temporal para ver cambios antes de mergear.
Servidor propio: más flexible, un poco más complejo
Mi proyecto va en servidores propios por control. Hay que configurar SSH y que Actions ejecute comandos remotos.
Genera un par de claves en local:
ssh-keygen -t ed25519 -C "github-actions"
Añade la pública a ~/.ssh/authorized_keys del servidor y la privada a GitHub Secrets (por ejemplo SSH_PRIVATE_KEY).
Job de despliegue:
jobs:
deploy:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/my-nextjs-app
git pull origin main
npm install
npm run build
pm2 restart nextjs-app
SSH al servidor, pull, install, build y restart —todo automatizado.
Build ID consistente en varios servidores
Con balanceo en varios servidores, los build ID deben coincidir; si no, el usuario ve recargas constantes.
Solución: construir en un solo sitio y distribuir el artefacto:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm ci
- run: npm run build
# Subir artefactos del build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: next-build
path: |
.next
public
deploy:
runs-on: ubuntu-latest
needs: build
strategy:
matrix:
server: [server1, server2, server3] # varios servidores
steps:
# Descargar artefactos
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: next-build
# Desplegar en cada servidor
- name: Deploy to ${{ matrix.server }}
uses: appleboy/scp-action@master
with:
host: ${{ secrets[format('{0}_HOST', matrix.server)] }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: ".next,public"
target: "/var/www/my-nextjs-app"
Un solo build, mismo artefacto en los tres servidores: build ID alineado.
Optimización y buenas prácticas
Si falla el build
La automatización mola, pero a veces falla. Si no te enteras, el código está en GitHub y producción no se actualizó.
Configuro notificaciones: email, Slack o similar. Ejemplo con Slack:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
[... pasos de despliegue ...]
# Notificar si falla el despliegue
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: '¡Falló el despliegue! Revisa qué pasó'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
channel: '#deploy-notifications'
Si falla, Slack avisa al momento.
Ramas: staging y producción
Uso ramas distintas por entorno: develop → staging, main → producción:
on:
push:
branches:
- main # producción
- develop # staging
jobs:
deploy-staging:
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
steps:
- [... despliegue a staging ...]
deploy-production:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- [... despliegue a producción ...]
Desarrollo en develop con despliegue automático a staging; merge a main cuando esté validado.
Algunos equipos exigen aprobación manual antes de producción. En el job:
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production # entorno con aprobación
steps: [...]
El workflow se pausa hasta que un revisor apruebe. Capa extra de seguridad en proyectos críticos.
Rollback
Aun con pruebas y aprobación, a veces hay incidentes en producción. Hay que volver atrás rápido.
Esquema simple: tag por despliegue y conservar artefactos recientes. Un workflow manual con workflow_dispatch y el tag objetivo:
on:
workflow_dispatch: # disparo manual
inputs:
tag:
description: 'Tag al que hacer rollback'
required: true
jobs:
rollback:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.tag }} # checkout del tag indicado
- name: Deploy
[... flujo de despliegue normal ...]
En Actions, Run workflow, introduces el tag y listo.
Variables de entorno
Next.js suele necesitar URL de API, cadena de conexión a BD, etc. No las hardcodees ni las subas al repo.
Buenas prácticas:
- Secretos sensibles en GitHub Secrets
- Inyectar en el workflow como variables de entorno
- Next.js las lee en build time
- name: Build
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ secrets.API_URL }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
Distinto entorno, distintos secrets; el código no cambia.
Caso práctico: configuración completa
Ejemplo con pruebas, build y despliegue listo para adaptar:
name: Next.js CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
# Job 1: lint y pruebas
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint check
run: npm run lint
- name: Type check
run: npm run type-check
- name: Run tests
run: npm run test -- --coverage
# Job 2: build
build:
runs-on: ubuntu-latest
needs: test # solo tras pasar pruebas
if: github.event_name == 'push' # build en push, no en PR
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Cache dependencies and build
uses: actions/cache@v3
with:
path: |
~/.npm
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ secrets.API_URL }}
# Subir artefactos para despliegue
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: next-build
path: |
.next
public
package.json
# Job 3: despliegue a staging
deploy-staging:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/develop'
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: next-build
- name: Deploy to staging server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.STAGING_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/staging
pm2 stop nextjs-app || true
rm -rf .next public
pm2 start npm --name "nextjs-app" -- start
pm2 save
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Despliegue a staging ${{ job.status == "success" && "correcto" || "fallido" }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
# Job 4: despliegue a producción
deploy-production:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
environment:
name: production # requiere aprobación manual
steps:
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: next-build
- name: Deploy to production server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/production
pm2 stop nextjs-app || true
rm -rf .next public
pm2 start npm --name "nextjs-app" -- start
pm2 save
- name: Notify Slack
if: always()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Despliegue a producción ${{ job.status == "success" && "correcto" || "fallido" }}'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
En un PR solo corren pruebas. Push a develop despliega a staging; push a main a producción (con aprobación). Slack en cada despliegue.
Secrets típicos en el repo:
API_URL: URL de la APISTAGING_HOST/PROD_HOST: hosts de staging y producciónSERVER_USER: usuario SSHSSH_PRIVATE_KEY: clave privada SSHSLACK_WEBHOOK: webhook de Slack (opcional)
Configurado eso, escribes código, haces commit y el resto va solo.
Conclusión
Pasar de despliegue manual a automatizado cambió cómo trabajo. Ya no repito comandos en el servidor, no olvido pruebas ni espero mirando la terminal.
Montar CI/CD con GitHub Actions lleva tiempo al principio, pero compensa. Empieza simple: pruebas y build; luego despliegue, notificaciones y rollback.
Honestamente, no sé cómo desplegaba a mano antes. Si sigues en manual, merece la pena invertir un rato. Push, café, y la nueva versión online — una vez que lo pruebas, cuesta volver atrás.
Manos a la obra: en tu proyecto Next.js crea el primer workflow y mira cómo GitHub Actions lo ejecuta solo. Ahí entenderás de qué hablo.
Configuración completa de CI/CD para Next.js
Pasos completos desde crear el workflow de GitHub Actions hasta configurar pruebas, build y despliegue
⏱️ Estimated time: 2 hr
- 1
Step 1: Crear el workflow de GitHub Actions
Crea `.github/workflows/deploy.yml`:
```yaml
name: Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm install
- run: npm run build
- run: npm test
```
Puntos clave:
• Disparador: push a main
• Entorno: ubuntu-latest
• Pasos: checkout → setup-node → install → build → test - 2
Step 2: Configurar pasos de prueba
Añade pruebas:
```yaml
- name: Run tests
run: npm test
- name: Type check
run: npm run type-check
- name: Lint
run: npm run lint
```
Puntos clave:
• Si fallan las pruebas, no hay despliegue
• Type check para seguridad de tipos
• Lint para calidad de código
Ventajas:
• Evita desplegar código con problemas
• Comprobaciones automáticas, sin olvidar las pruebas - 3
Step 3: Configurar el paso de build
Configuración de build:
```yaml
- name: Build
run: npm run build
env:
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
```
Optimización con caché:
```yaml
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
```
Puntos clave:
• Variables de entorno en build
• Caché para acelerar
• Revisar la salida del build - 4
Step 4: Configurar el paso de despliegue
Despliegue por SSH:
```yaml
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /path/to/app
git pull
npm install
npm run build
pm2 restart app
```
Despliegue multi-servidor:
```yaml
- name: Deploy to servers
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOSTS }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /path/to/app
git pull
npm install
# Usar artefacto construido en GitHub Actions
pm2 restart app
```
Puntos clave:
• Autenticación con clave SSH
• Build ID unificado (build en GitHub Actions)
• Evitar builds distintos en cada servidor
FAQ
¿Por qué necesitas CI/CD?
• Repetir operaciones en el servidor tras cada cambio
• Olvidar reiniciar servidores
• Olvidar ejecutar pruebas
• Errores frecuentes con varios servidores
• Build ID distintos que provocan hard refresh
Ventajas de CI/CD:
• Pruebas, build y despliegue automatizados
• Push y el código sale en producción
• Menos errores manuales
• Build ID unificado
• Más eficiencia de desarrollo
Casos reales:
• Tres servidores: dos OK, el tercero con SSH cortado sin darse cuenta
• Balanceo enviando tráfico a servidor sin actualizar: usuarios ven versión antigua
• Despliegue sin pruebas por prisa: bug grave en producción
Solución: automatizar todo el flujo con GitHub Actions.
¿Cómo configurar GitHub Actions?
```yaml
name: Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm install
- run: npm run build
- run: npm test
```
Puntos clave:
• Disparador: push a main
• Entorno: ubuntu-latest
• Pasos: checkout → setup-node → install → build → test
Configurar Secrets:
• En Settings → Secrets del repositorio
• HOST, USERNAME, SSH_KEY, etc.
• Para despliegue SSH
Recomendación: empieza con lo mínimo, haz funcionar pruebas y build, y luego añade despliegue.
¿Cómo evitar build ID distintos en despliegue multi-servidor?
Solución: build ID unificado
Construir en GitHub Actions:
```yaml
- name: Build
run: npm run build
- name: Deploy to servers
uses: appleboy/ssh-action@master
with:
script: |
cd /path/to/app
git pull
# Usar artefacto construido en GitHub Actions
pm2 restart app
```
O con artefactos de build:
```yaml
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: .next
- name: Deploy to servers
uses: appleboy/ssh-action@master
with:
script: |
# Descargar artefacto
# Desplegar en servidores
```
Puntos clave:
• Build único en GitHub Actions
• Distribuir el mismo artefacto a varios servidores
• No construir en cada servidor
Ventajas:
• Build ID consistente
• Sin hard refresh forzado
• Mejor experiencia de usuario
¿Cómo configurar los pasos de prueba?
```yaml
- name: Run tests
run: npm test
- name: Type check
run: npm run type-check
- name: Lint
run: npm run lint
```
Puntos clave:
• Fallo en pruebas bloquea despliegue
• Type check para tipos
• Lint para calidad
Ventajas:
• No desplegar código roto
• Comprobaciones automáticas
• Mejor calidad de código
Recomendación:
• Empieza con pruebas simples
• Sube cobertura gradualmente
• Mejora continua
¿Cómo configurar notificaciones de despliegue?
```yaml
- name: Notify Slack
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Despliegue completado'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
```
Notificación por email:
```yaml
- name: Send email
uses: dawidd6/action-send-mail@v3
with:
to: [email protected]
subject: 'Despliegue completado'
body: 'Despliegue a producción completado correctamente'
```
Puntos clave:
• Notificar éxito y fallo
• Incluir versión, hora, etc.
• Avisar al equipo al momento
Recomendación:
• Slack para tiempo real
• Email como respaldo
• Incluir detalles del despliegue
¿Cuáles son las buenas prácticas de CI/CD?
1. Haz funcionar pruebas y build
2. Añade despliegue
3. Luego notificaciones y rollback
No intentes todo de golpe; primero el flujo básico y luego refina.
Mejora continua:
• Revisa logs tras cada despliegue
• Ajusta según la realidad
• Optimiza tiempo de build
• Sube cobertura de pruebas
Métricas clave:
• Tiempo de build
• Tasa de éxito de pruebas
• Tasa de éxito de despliegue
• Número de rollbacks
Recomendación:
• Empieza simple
• Mejora de forma continua
• Trabajo en equipo
Recuerda: CI/CD no es un proyecto único, es un proceso continuo.
12 min de lectura · Publicado el: 20 dic 2025 · Actualizado el: 21 ago 2026
Guía completa de Next.js
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Guía completa para desplegar Next.js en Vercel: variables de entorno, dominio personalizado y monitorización de rendimiento
Guía completa para desplegar Next.js en Vercel: configuración de variables de entorno, vinculación de dominio personalizado, certificados SSL y monitorización de rendimiento, evitando los errores más habituales de principiantes.
Parte 40 de 51
Siguiente
Escapar de Vercel: guía completa de autoalojamiento de Next.js con Docker
¿Cansado de las facturas altas de Vercel? Esta guía te enseña a autoalojar Next.js con Docker: configuración standalone, proxy inverso y solución para el streaming, ahorrando $300-500 al mes.
Parte 42 de 51



Comentarios
Inicia sesión con GitHub para dejar un comentario