kb.erickguedes.com
Nitro: Servidor Universal para UnJS

Deploy Multi-Plataforma

Aula 4 de 4

Deployment

Nitro foi projetado para ser universal: o mesmo código pode ser deployado em múltiplas plataformas sem alterações.

Presets

Cada plataforma tem um preset que otimiza o build para aquele ambiente.

// nitro.config.ts
export default defineNitroConfig({
  preset: 'node-server'  // ou 'vercel', 'netlify', 'cloudflare', etc
});

Node.js Server

// nitro.config.ts
export default defineNitroConfig({
  preset: 'node-server',  // padrão
  node: {
    // Opções específicas do Node
  }
});
# Build
npm run build

# Estrutura gerada
.output/
├── public/
│   └── ... (arquivos estáticos)
├── server/
│   ├── index.mjs          # Entry point
│   └── index.mjs.map
└── nitro.json

# Iniciar
node .output/server/index.mjs
// Server custom (se precisar)
const { createNitroApp } = require('./.output/server/index.mjs');
const { toNodeListener } = require('h3');
const http = require('http');

const app = createNitroApp();
const server = http.createServer(toNodeListener(app.h3App));

server.listen(3000);

Vercel

// nitro.config.ts
export default defineNitroConfig({
  preset: 'vercel'
});
npm run build
vercel --prod
// vercel.json (opcional)
{
  "buildCommand": "npm run build",
  "outputDirectory": ".output",
  "installCommand": "npm install"
}

Edge Functions na Vercel

// nitro.config.ts
export default defineNitroConfig({
  preset: 'vercel-edge',  // Edge functions
  vercel: {
    regions: ['gru1'],    // São Paulo
    nodeVersion: 20
  }
});

Netlify

// nitro.config.ts
export default defineNitroConfig({
  preset: 'netlify'
});
npm run build
netlify deploy --prod
# netlify.toml
[build]
  command = "npm run build"
  publish = ".output/public"
  functions = ".output/functions"

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

Cloudflare Workers

// nitro.config.ts
export default defineNitroConfig({
  preset: 'cloudflare-pages',  // Cloudflare Pages
  // ou 'cloudflare-workers'
  cloudflare: {
    // Bindings
    bindings: [
      {
        name: 'MY_KV',
        type: 'kv_namespace',
        namespace_id: 'xxxx'
      }
    ]
  }
});
npm run build
npx wrangler pages deploy .output/public
# wrangler.toml (Cloudflare Workers)
name = "my-nitro-app"
compatibility_date = "2024-01-01"

[[kv_namespaces]]
binding = "MY_KV"
id = "xxxx"

Deno Deploy

// nitro.config.ts
export default defineNitroConfig({
  preset: 'deno-deploy'
});
npm run build
deployctl deploy --project=my-app .output/server/index.ts

AWS Lambda

// nitro.config.ts
export default defineNitroConfig({
  preset: 'aws-lambda'
});
npm run build
# O .output será compatível com Lambda
# Use Serverless Framework ou CDK para deploy
# serverless.yml
service: nitro-api

provider:
  name: aws
  runtime: nodejs20.x

functions:
  api:
    handler: .output/server/index.handler
    events:
      - httpApi: '*'

Build Output

.output/
├── public/                    # Arquivos estáticos (prerendered)
│   └── index.html
├── server/
│   ├── index.mjs              # Servidor principal
│   ├── index.mjs.map
│   ├── chunks/                # Chunks do bundle
│   ├── node_modules/          # Dependencies necessárias
│   └── package.json
├── nitro.json                 # Config do build
└── presets/                   # Info do preset usado

Estrutura detalhada

.output/
├── public/
│   ├── about/
│   │   └── index.html         # Páginas pré-renderizadas
│   ├── blog/
│   │   └── index.html
│   └── _nuxt/                 # Assets estáticos
├── server/
│   ├── index.mjs              # Entry point universal
│   ├── chunks/
│   │   ├── routes/
│   │   │   ├── api.users.mjs
│   │   │   └── index.mjs
│   │   └── handlers.mjs
│   └── node_modules/
└── nitro.json

Variáveis de Ambiente

// nitro.config.ts
export default defineNitroConfig({
  runtimeConfig: {
    public: {
      apiUrl: process.env.API_URL || '/api'
    },
    private: {
      databaseUrl: process.env.DATABASE_URL,
      apiKey: process.env.API_KEY
    }
  }
});
# Node.js
export DATABASE_URL=postgresql://...
export API_KEY=secret
node .output/server/index.mjs

# Vercel
vercel env add DATABASE_URL
vercel env add API_KEY

# Docker
docker run -e DATABASE_URL=postgresql://... -e API_KEY=secret my-app

Multi-Platform Deployment

// nitro.config.ts
import { defineNitroConfig } from 'nitro/config';

export default defineNitroConfig({
  // Config compartilhada
  runtimeConfig: {
    public: {
      siteUrl: process.env.SITE_URL || 'http://localhost:3000'
    }
  },

  // Storage condicional
  storage: {
    'data': process.env.CF_PAGES
      ? { driver: 'cloudflare-kv-binding', binding: 'DATA_KV' }
      : { driver: 'fs', base: './data' }
  },

  // Route rules universais
  routeRules: {
    '/': { prerender: true },
    '/api/**': { cors: true },
    '/blog/**': { isr: 3600 }
  }
});
# Deploy para Node.js
npm run build --preset node-server
node .output/server/index.mjs

# Deploy para Vercel
npm run build --preset vercel
vercel --prod

# Deploy para Cloudflare
npm run build --preset cloudflare-pages
npx wrangler pages deploy .output/public

Lab: Exercício - Deploy Completo

# 1. Build para Node.js
npm run build
node .output/server/index.mjs &

# 2. Testar
curl http://localhost:3000/health

# 3. Deploy na Vercel
npm run build --preset vercel
vercel --prod

# 4. Deploy no Cloudflare
npm run build --preset cloudflare-pages
npx wrangler pages deploy .output/public --project-name=my-app
// nitro.config.ts
export default defineNitroConfig({
  preset: process.env.DEPLOY_TARGET || 'node-server',
  runtimeConfig: {
    public: {
      version: '1.0.0'
    }
  },
  routeRules: {
    '/': { prerender: true },
    '/api/health': { ssr: true }
  }
});
# Deploy para diferentes plataformas
DEPLOY_TARGET=node-server npm run build
DEPLOY_TARGET=vercel npm run build
DEPLOY_TARGET=cloudflare-pages npm run build

Nitro permite deploy no mesmo código para Node.js, Vercel, Netlify, Cloudflare Workers, Deno, AWS Lambda e mais. O preset otimiza o build para cada plataforma. Runtime config separa dados públicos e privados. Multi-platform sem mudar código.