Deployment
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
Create an Edge Function
Create a file in the api/ directory:
api/hello.tstypescript
1// api/hello.ts
2import { createAppEdge } from '@morojs/moro';
3
4const app = await 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// Export for Vercel
23export default app.getHandler();
24
25// Optional: Export specific HTTP methods
26export const GET = app.getHandler();
27export const POST = app.getHandler();Configure Vercel
Create a vercel.json file:
vercel.jsontypescript
1{
2 "functions": {
3 "api/**/*.ts": {
4 "runtime": "@vercel/edge"
5 }
6 },
7 "regions": ["all"]
8}Deploy to Vercel
Deploy using the Vercel CLI:
typescript
1# Install Vercel CLI
2npm install -g vercel
3
4# Login to Vercel
5vercel login
6
7# Deploy
8vercel --prodReference
Project Structure
Recommended Project Structuretypescript
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.tstypescript
1// api/app.ts
2import { createAppEdge } from '@morojs/moro';
3import { z } from 'zod';
4
5const app = await 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
64export default app.getHandler();Edge Database Integration
lib/edge-db.tstypescript
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 = await 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
49export default app.getHandler();Environment Variables
Environment Configurationtypescript
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.localGitHub Actions Deployment
.github/workflows/deploy.ymltypescript
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:
typescript
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:
typescript
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 APIsEnvironment Variables Not Loading
Ensure environment variables are set in Vercel dashboard or via CLI:
typescript
1# Set environment variable
2vercel env add DATABASE_URL production
3
4# Pull environment variables
5vercel env pull .env.local