Nuxt.js Deployment DevOps Production

Desplegar Nuxt 3 en producción: Guía completa

Pablo Alcalde García

Desplegar Nuxt 3 en producción: Guía completa

Cómo llevar tu aplicación Nuxt de desarrollo a producción sin problemas.

Preparación pre-deployment

1. Variables de entorno

# .env.production
NUXT_PUBLIC_API_URL=https://api.produccion.com
NUXT_PRIVATE_API_KEY=xxx
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    // Private (solo servidor)
    apiKey: process.env.NUXT_PRIVATE_API_KEY,
    
    // Public (cliente y servidor)
    public: {
      apiUrl: process.env.NUXT_PUBLIC_API_URL
    }
  }
})

2. Optimización

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    compressPublicAssets: true,
    minify: true,
    prerender: {
      crawlLinks: true,
      routes: ['/sitemap.xml']
    }
  },
  
  experimental: {
    payloadExtraction: true
  },
  
  image: {
    formats: ['avif', 'webp']
  }
})

3. Build test

npm run build
npm run preview

Netlify

Setup

npm install -D @netlify/edge-functions
# netlify.toml
[build]
  command = "npm run build"
  publish = ".output/public"

[[redirects]]
  from = "/*"
  to = "/.netlify/functions/server"
  status = 200

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-Content-Type-Options = "nosniff"
    Referrer-Policy = "strict-origin-when-cross-origin"

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

Deployment

# Via CLI
npm install -D netlify-cli
netlify deploy --prod

# O conecta repo en Netlify UI

Environment Variables

# En Netlify UI
Site settings > Environment variables

Vercel

Preset automático

Nuxt detecta Vercel automáticamente.

// nuxt.config.ts - ya incluido
export default defineNuxtConfig({
  nitro: {
    preset: 'vercel'
  }
})

vercel.json

{
  "buildCommand": "npm run build",
  "devCommand": "npm run dev",
  "installCommand": "npm install",
  "framework": "nuxtjs",
  "outputDirectory": ".output/public"
}

Deployment

# Via CLI
npm install -g vercel
vercel --prod

# O via Git push
git push origin main

Edge Functions

// server/middleware/edge.ts
export default defineEventHandler(async (event) => {
  event.node.res.setHeader('x-edge', 'true')
})

Cloudflare Pages

Build settings

# wrangler.toml
name = "mi-app-nuxt"
compatibility_date = "2024-01-01"

[build]
command = "npm run build"

[site]
bucket = ".output/public"

Deploy

npm install -D wrangler
npx wrangler pages deploy .output/public

Workers

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'cloudflare-pages'
  }
})

Docker

Dockerfile

FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

FROM node:20-alpine

WORKDIR /app

COPY --from=builder /app/.output ./.output
COPY --from=builder /app/package*.json ./

ENV HOST=0.0.0.0
ENV PORT=3000
ENV NODE_ENV=production

EXPOSE 3000

CMD ["node", ".output/server/index.mjs"]

docker-compose.yml

version: '3.8'

services:
  nuxt-app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NUXT_PUBLIC_API_URL=https://api.example.com
    restart: unless-stopped

Build y run

docker build -t mi-app-nuxt .
docker run -p 3000:3000 mi-app-nuxt

Node.js Server

PM2

npm install -g pm2
// ecosystem.config.js
module.exports = {
  apps: [{
    name: 'nuxt-app',
    script: './.output/server/index.mjs',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      PORT: 3000
    }
  }]
}
# Deploy
npm run build
pm2 start ecosystem.config.js
pm2 save
pm2 startup

Static Hosting

Para SSG

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: false, // SPA
  // O
  nitro: {
    static: true // SSG
  }
})
npm run generate
# Output en .output/public

GitHub Pages

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Generate
        run: npm run generate
      
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: .output/public

CI/CD Pipeline

GitHub Actions

# .github/workflows/ci.yml
name: CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: '20'
          cache: 'npm'
      
      - name: Install
        run: npm ci
      
      - name: Lint
        run: npm run lint
      
      - name: Test
        run: npm run test
      
      - name: Build
        run: npm run build

Monitoring

Sentry

npm install @sentry/vue
// plugins/sentry.client.ts
import * as Sentry from '@sentry/vue'

export default defineNuxtPlugin((nuxtApp) => {
  Sentry.init({
    app: nuxtApp.vueApp,
    dsn: 'YOUR_SENTRY_DSN',
    environment: process.env.NODE_ENV,
    tracesSampleRate: 1.0
  })
})

Analytics

// plugins/analytics.client.ts
export default defineNuxtPlugin(() => {
  // Google Analytics
  if (process.client) {
    window.dataLayer = window.dataLayer || []
    function gtag() { dataLayer.push(arguments) }
    gtag('js', new Date())
    gtag('config', 'GA_MEASUREMENT_ID')
  }
})

Performance Checklist

Pre-deployment:

  • Lighthouse score > 90
  • Core Web Vitals optimizados
  • Imágenes optimizadas
  • Code splitting implementado
  • Lazy loading configurado
  • Caché configurado
  • CDN para assets estáticos
  • Compresión Gzip/Brotli
  • Security headers
  • HTTPS habilitado

Troubleshooting

Error: “Cannot find module”

# Limpiar y reinstalar
rm -rf .nuxt .output node_modules
npm install
npm run build

Error 500 en producción

// Habilitar logs
export default defineNuxtConfig({
  nitro: {
    logLevel: 4
  }
})

Assets no cargan

// Verificar base URL
export default defineNuxtConfig({
  app: {
    cdnURL: 'https://cdn.ejemplo.com'
  }
})

Mi stack en producción

En Wegow usamos:

  • Hosting: Netlify
  • CDN: Cloudflare
  • Monitoring: Sentry
  • Analytics: Google Analytics 4
  • CI/CD: GitHub Actions
  • Performance: Cloudinary (imágenes)

Conclusión

Nuxt 3 hace el deployment muy sencillo. Elige la plataforma que mejor se adapte a tu proyecto y sigue estas mejores prácticas.

¿Te ha gustado este artículo?

Si tienes preguntas o quieres discutir sobre estos temas, no dudes en contactarme.

Contáctame
Escríbeme por WhatsApp