Features
Docs
CLI
Benchmarks
Examples

© 2024 MoroJs

Vercel Edge Deployment

Deploy your MoroJS applications to Vercel Edge Runtime for ultra-fast performance and global distribution with zero cold starts.

Overview

Vercel Edge Runtime provides ultra-fast performance with zero cold starts and global distribution. MoroJS provides native support for Vercel Edge Runtime with the same API you use for Node.js development.

Edge Runtime Benefits

  • • Zero cold start latency
  • • Global edge deployment
  • • Automatic scaling
  • • Smaller bundle sizes
  • • Enhanced security

Quick Start

1

Create an Edge Function

Create a file in the api/ directory:

api/hello.ts

typescript

1// api/hello.ts
2import { createAppEdge } from '@morojs/moro';
3
4const app = createAppEdge();
5
6app.get('/', () => {
7  return { message: 'Hello from Vercel Edge!' };
8});
9
10app.post('/users', {
11  body: z.object({
12    name: z.string(),
13    email: z.string().email()
14  }),
15  handler: ({ body }) => {
16    return {
17      success: true,
18      user: body
19    };
20  }
21});
22
23// Export for Vercel
24export default app.getHandler();
25
26// Optional: Export specific HTTP methods
27export const GET = app.getHandler();
28export const POST = app.getHandler();
2

Configure Vercel

Create a vercel.json file:

vercel.json

typescript

1{
2  "functions": {
3    "api/**/*.ts": {
4      "runtime": "@vercel/edge"
5    }
6  },
7  "regions": ["all"]
8}
3

Deploy to Vercel

Deploy using the Vercel CLI:

1# Install Vercel CLI
2npm install -g vercel
3
4# Login to Vercel
5vercel login
6
7# Deploy
8vercel --prod

Reference

Project Structure

Recommended Project Structure

typescript

1my-moro-app/
2├── api/
3│   ├── auth/
4│   │   ├── login.ts
5│   │   └── callback.ts
6│   ├── users/
7│   │   ├── index.ts
8│   │   └── [id].ts
9│   └── hello.ts
10├── lib/
11│   ├── auth.ts
12│   ├── db.ts
13│   └── utils.ts
14├── package.json
15├── vercel.json
16└── tsconfig.json
17
18// package.json
19{
20  "name": "my-moro-app",
21  "version": "1.0.0",
22  "scripts": {
23    "dev": "vercel dev",
24    "build": "tsc",
25    "deploy": "vercel"
26  },
27  "dependencies": {
28    "@morojs/moro": "^1.0.0",
29    "zod": "^3.22.0"
30  },
31  "devDependencies": {
32    "@vercel/node": "^3.0.0",
33    "typescript": "^5.0.0",
34    "vercel": "^32.0.0"
35  }
36}

Edge-Optimized Application

api/app.ts

typescript

1// api/app.ts
2import { createAppEdge } from '@morojs/moro';
3import { z } from 'zod';
4
5const app = createAppEdge({
6  // Edge-specific configuration
7  runtime: {
8    // Memory limit for edge function
9    memory: 128, // MB
10    
11    // Maximum execution duration
12    maxDuration: 30, // seconds
13    
14    // Regions to deploy to
15    regions: ['iad1', 'sfo1', 'fra1'], // or 'all'
16  },
17  
18  // CORS for edge
19  cors: {
20    origin: ['https://myapp.com', 'https://admin.myapp.com'],
21    credentials: false // Cookies not supported in edge
22  },
23  
24  // Edge-compatible features only
25  features: {
26    // File system not available in edge
27    fileSystem: false,
28    
29    // Streaming responses supported
30    streaming: true,
31    
32    // WebCrypto API available
33    crypto: true
34  }
35});
36
37// Global middleware for edge
38app.use(async (context, next) => {
39  // Add edge-specific headers
40  context.response.headers.set('X-Edge-Runtime', 'vercel');
41  context.response.headers.set('X-Edge-Region', process.env.VERCEL_REGION || 'unknown');
42  
43  await next();
44});
45
46// Geolocation-aware routing
47app.get('/api/location', {
48  handler: ({ request }) => {
49    // Access Vercel edge headers
50    const country = request.headers.get('x-vercel-ip-country') || 'unknown';
51    const city = request.headers.get('x-vercel-ip-city') || 'unknown';
52    const region = request.headers.get('x-vercel-ip-country-region') || 'unknown';
53    
54    return {
55      country,
56      city,
57      region,
58      timezone: request.headers.get('x-vercel-ip-timezone'),
59      latitude: request.headers.get('x-vercel-ip-latitude'),
60      longitude: request.headers.get('x-vercel-ip-longitude')
61    };
62  }
63});
64
65export default app.getHandler();

Edge Database Integration

lib/edge-db.ts

typescript

1// lib/edge-db.ts
2import { createClient } from '@planetscale/database';
3
4// Edge-compatible database clients
5const db = createClient({
6  url: process.env.DATABASE_URL
7});
8
9// Redis for edge (Upstash)
10import { Redis } from '@upstash/redis';
11
12const redis = new Redis({
13  url: process.env.UPSTASH_REDIS_REST_URL,
14  token: process.env.UPSTASH_REDIS_REST_TOKEN
15});
16
17// api/users/[id].ts
18import { createAppEdge } from '@morojs/moro';
19import { db, redis } from '../../lib/edge-db';
20
21const app = createAppEdge();
22
23app.get('/api/users/:id', {
24  params: z.object({
25    id: z.string().uuid()
26  }),
27  handler: async ({ params }) => {
28    // Try cache first
29    const cached = await redis.get(`user:${params.id}`);
30    if (cached) {
31      return JSON.parse(cached);
32    }
33    
34    // Query database
35    const result = await db.execute(
36      'SELECT id, name, email FROM users WHERE id = ?',
37      [params.id]
38    );
39    
40    const user = result.rows[0];
41    if (user) {
42      // Cache for 5 minutes
43      await redis.setex(`user:${params.id}`, 300, JSON.stringify(user));
44    }
45    
46    return user || { error: 'User not found' };
47  }
48});
49
50export default app.getHandler();

Environment Variables

Environment Configuration

typescript

1// .env.local (for development)
2DATABASE_URL=mysql://user:pass@host/db
3UPSTASH_REDIS_REST_URL=https://...
4UPSTASH_REDIS_REST_TOKEN=...
5JWT_SECRET=your-secret-key
6VERCEL_ENV=development
7
8// lib/config.ts
9const config = {
10  database: {
11    url: process.env.DATABASE_URL!
12  },
13  redis: {
14    url: process.env.UPSTASH_REDIS_REST_URL!,
15    token: process.env.UPSTASH_REDIS_REST_TOKEN!
16  },
17  auth: {
18    jwtSecret: process.env.JWT_SECRET!
19  },
20  vercel: {
21    env: process.env.VERCEL_ENV || 'development',
22    region: process.env.VERCEL_REGION || 'local'
23  }
24};
25
26export default config;
27
28// Vercel CLI commands for environment variables
29// vercel env add JWT_SECRET production
30// vercel env add DATABASE_URL production
31// vercel env pull .env.local

GitHub Actions Deployment

.github/workflows/deploy.yml

typescript

1# .github/workflows/deploy.yml
2name: Deploy to Vercel
3
4on:
5  push:
6    branches: [main]
7  pull_request:
8    branches: [main]
9
10jobs:
11  deploy:
12    runs-on: ubuntu-latest
13    
14    steps:
15      - uses: actions/checkout@v3
16      
17      - name: Setup Node.js
18        uses: actions/setup-node@v3
19        with:
20          node-version: '18'
21          cache: 'npm'
22      
23      - name: Install dependencies
24        run: npm ci
25      
26      - name: Build project
27        run: npm run build
28      
29      - name: Deploy to Vercel
30        uses: amondnet/vercel-action@v25
31        with:
32          vercel-token: ${{ secrets.VERCEL_TOKEN }}
33          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
34          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
35          vercel-args: '--prod'
36        if: github.ref == 'refs/heads/main'

Troubleshooting

Function Timeout

Edge functions have a maximum execution time. Increase it in vercel.json:

1{
2  "functions": {
3    "api/**/*.ts": {
4      "runtime": "@vercel/edge",
5      "maxDuration": 30
6    }
7  }
8}

Node.js APIs Not Available

Edge Runtime doesn't support all Node.js APIs. Use edge-compatible alternatives:

1// ❌ Not available in Edge
2import fs from 'fs';
3import path from 'path';
4
5// ✅ Use edge-compatible alternatives
6import { createAppEdge } from '@morojs/moro';
7// Use Web APIs instead of Node.js APIs

Environment Variables Not Loading

Ensure environment variables are set in Vercel dashboard or via CLI:

1# Set environment variable
2vercel env add DATABASE_URL production
3
4# Pull environment variables
5vercel env pull .env.local

Next Steps