Exemples Vercel Deployment

Exemples de configuration Vercel deployment incluant vercel.json, serverless functions et edge functions

Key Facts

Category
Deployment
Items
4
Format Families
json, image

Sample Overview

Exemples de configuration Vercel deployment incluant vercel.json, serverless functions et edge functions This sample set belongs to Deployment and can be used to test related workflows inside Elysia Tools.

💻 Configuration Vercel de Base json

🟢 simple

Configuration Vercel de base avec domaines personnalisés, paramètres de build et variables d'environnement

⏱️ 10 min 🏷️ vercel, configuration, deployment
Prerequisites: Vercel basics, JavaScript/TypeScript
{
  "version": 2,
  "name": "my-app",
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/static-build",
      "config": {
        "distDir": "build"
      }
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "/build/$1"
    }
  ],
  "env": {
    "NODE_ENV": "production"
  },
  "build": {
    "env": {
      "CUSTOM_KEY": "value"
    }
  },
  "functions": {
    "pages/api/**/*.js": {
      "maxDuration": 10
    }
  }
}

💻 Configuration Vercel Next.js json

🟡 intermediate ⭐⭐⭐

Configuration Next.js avancée avec ISR, optimisation d'images et support monorepo

⏱️ 20 min 🏷️ vercel, next.js, framework
Prerequisites: Next.js, Vercel deployment, JavaScript/TypeScript
{
  "version": 2,
  "name": "nextjs-app",
  "buildCommand": "npm run build",
  "outputDirectory": ".next",
  "installCommand": "npm install",
  "framework": "nextjs",
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/next"
    }
  ],
  "functions": {
    "pages/api/**/*.js": {
      "maxDuration": 30,
      "memory": 1024
    }
  },
  "rewrites": [
    {
      "source": "/blog/:path*",
      "destination": "/blog?slug=:path*"
    },
    {
      "source": "/((?!api|_next/static|_next/image|favicon.ico).*)",
      "destination": "/pages/$1"
    }
  ],
  "redirects": [
    {
      "source": "/old-path/:path*",
      "destination": "/new-path/:path*",
      "permanent": true
    }
  ],
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "s-maxage=86400"
        },
        {
          "key": "Access-Control-Allow-Origin",
          "value": "*"
        }
      ]
    },
    {
      "source": "/(.*)\.(js|css|png|jpg|jpeg|gif|ico|svg)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ],
  "images": {
    "domains": ["example.com", "cdn.example.com"],
    "sizes": [16, 32, 48, 64, 96, 128, 256, 384],
    "minimumCacheTTL": 60,
    "format": ["image/webp", "image/avif"]
  }
}

💻 Vercel Serverless Functions javascript

🟡 intermediate ⭐⭐⭐

Exemples de serverless functions avec différents runtimes et cas d'usage

⏱️ 25 min 🏷️ vercel, functions, serverless, api
Prerequisites: JavaScript/TypeScript, API development, Serverless concepts
// Vercel Serverless Functions Examples

// 1. API Route with Node.js (Next.js)
// pages/api/users.js
export async function usersHandler(req, res) {
  if (req.method === 'GET') {
    try {
      // Fetch users from database
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const users = await response.json();

      res.status(200).json(users);
    } catch (error) {
      res.status(500).json({ error: 'Failed to fetch users' });
    }
  } else if (req.method === 'POST') {
    try {
      const user = req.body;

      // Validate input
      if (!user.name || !user.email) {
        return res.status(400).json({ error: 'Name and email are required' });
      }

      // Create user logic here
      const newUser = {
        id: Date.now(),
        ...user,
        createdAt: new Date().toISOString()
      };

      res.status(201).json(newUser);
    } catch (error) {
      res.status(500).json({ error: 'Failed to create user' });
    }
  } else {
    res.setHeader('Allow', ['GET', 'POST']);
    res.status(405).end('Method Not Allowed');
  }
}

// 2. Edge Function with TypeScript
// api/edge-function.ts
import { NextRequest, NextResponse } from 'next/server';

export const config = {
  runtime: 'edge'
};

export function edgeFunctionHandler(req: NextRequest) {
  const url = req.nextUrl;
  const searchParams = url.searchParams;

  // Get IP address and user agent
  const ip = req.ip || req.headers.get('x-forwarded-for');
  const userAgent = req.headers.get('user-agent') || '';

  // Get geolocation from headers
  const country = req.headers.get('x-vercel-ip-country') || 'Unknown';
  const region = req.headers.get('x-vercel-ip-country-region') || 'Unknown';

  // Response with location data
  const response = {
    ip,
    userAgent,
    location: {
      country,
      region,
      city: req.headers.get('x-vercel-ip-city') || 'Unknown'
    },
    timestamp: new Date().toISOString()
  };

  return NextResponse.json(response, {
    status: 200,
    headers: {
      'Cache-Control': 's-maxage=60, stale-while-revalidate=300',
      'Access-Control-Allow-Origin': '*'
    }
  });
}

// 3. Background Function
// api/background-task.js
export async function backgroundTaskHandler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { email, data } = req.body;

    // Start background processing
    setTimeout(async () => {
      try {
        // Send email
        await fetch('https://api.resend.com/emails', {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${process.env.RESEND_API_KEY}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            from: '[email protected]',
            to: [email],
            subject: 'Your background task is complete',
            html: `<p>Your data has been processed: ${JSON.stringify(data, null, 2)}</p>`
          })
        });

        console.log('Background task completed successfully');
      } catch (error) {
        console.error('Background task failed:', error);
      }
    }, 0);

    res.status(202).json({
      message: 'Background task started',
      taskId: Date.now()
    });

  } catch (error) {
    res.status(500).json({ error: 'Failed to start background task' });
  }
}

// 4. Cron Job Function
// api/cron-job.js
export async function cronJobHandler(req, res) {
  // Verify cron secret
  const cronSecret = req.headers['x-vercel-cron-secret'];
  if (cronSecret !== process.env.CRON_SECRET) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  try {
    // Perform scheduled tasks
    const tasks = await Promise.allSettled([
      cleanupOldFiles(),
      sendDailyReports(),
      updateAnalytics()
    ]);

    const results = tasks.map((task, index) => ({
      task: ['cleanup', 'reports', 'analytics'][index],
      status: task.status,
      value: task.status === 'fulfilled' ? task.value : task.reason.message
    }));

    res.status(200).json({
      message: 'Cron job completed',
      timestamp: new Date().toISOString(),
      results
    });

  } catch (error) {
    res.status(500).json({ error: 'Cron job failed' });
  }
}

async function cleanupOldFiles() {
  // Cleanup logic here
  return 'Cleaned up 125 old files';
}

async function sendDailyReports() {
  // Report sending logic here
  return 'Sent 45 daily reports';
}

async function updateAnalytics() {
  // Analytics update logic here
  return 'Updated analytics data';
}

// 5. Webhook Handler
// api/webhook.js
import crypto from 'crypto';

export async function webhookHandler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const signature = req.headers['x-webhook-signature'];
  const secret = process.env.WEBHOOK_SECRET;

  // Verify webhook signature
  if (!verifySignature(req.body, signature, secret)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  try {
    const event = JSON.parse(req.body);

    switch (event.type) {
      case 'user.created':
        await handleUserCreated(event.data);
        break;
      case 'payment.completed':
        await handlePaymentCompleted(event.data);
        break;
      default:
        console.log('Unknown event type:', event.type);
    }

    res.status(200).json({ received: true });

  } catch (error) {
    res.status(500).json({ error: 'Failed to process webhook' });
  }
}

function verifySignature(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret);
  hmac.update(payload);
  const expectedSignature = hmac.digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature, 'hex'),
    Buffer.from(expectedSignature, 'hex')
  );
}

async function handleUserCreated(userData) {
  console.log('User created:', userData);
  // Handle user creation logic
}

async function handlePaymentCompleted(paymentData) {
  console.log('Payment completed:', paymentData);
  // Handle payment logic
}

💻 Configuration Vercel Monorepo json

🔴 complex ⭐⭐⭐⭐

Setup monorepo avec applications multiples, paquets partagés et gestion de workspaces

⏱️ 35 min 🏷️ vercel, monorepo, workspace
Prerequisites: Monorepo concepts, Vercel advanced, Turborepo/NX
{
  "version": 2,
  "name": "monorepo-app",
  "builds": [
    {
      "src": "apps/web/package.json",
      "use": "@vercel/next",
      "config": {
        "distDir": "build"
      }
    },
    {
      "src": "apps/api/package.json",
      "use": "@vercel/static-build",
      "config": {
        "outputDirectory": "dist"
      }
    },
    {
      "src": "apps/docs/package.json",
      "use": "@vercel/static-build",
      "config": {
        "outputDirectory": ".vitepress/dist"
      }
    }
  ],
  "installCommand": "npm install --workspaces --if-present",
  "routes": [
    {
      "src": "/api/(.*)",
      "dest": "/apps/api/$1"
    },
    {
      "src": "/docs/(.*)",
      "dest": "/apps/docs/$1"
    },
    {
      "handle": "filesystem"
    },
    {
      "src": "/(.*)",
      "dest": "/apps/web/$1"
    }
  ],
  "functions": {
    "apps/web/pages/api/**/*.js": {
      "maxDuration": 30
    },
    "apps/api/dist/**/*.js": {
      "maxDuration": 60
    }
  },
  "env": {
    "NODE_ENV": "production",
    "TURBOREPO_CACHE": "BLOB"
  },
  "build": {
    "env": {
      "VERCEL": "1",
      "TURBO_TOKEN": "@vercel/turbopack-token"
    }
  },
  "regions": ["iad1", "sfo1"],
  "framework": null
}