English

Edge computing brings your code closer to users for ultra-fast response times.

Vercel Edge Middleware

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  // Geolocation
  const country = request.geo?.country || 'US';
  const city = request.geo?.city || 'Unknown';

  // A/B Testing
  const bucket = Math.random() < 0.5 ? 'a' : 'b';

  const response = NextResponse.next();
  response.cookies.set('bucket', bucket);
  response.headers.set('x-user-location', `${city}, ${country}`);

  return response;
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

Edge Authentication

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { jwtVerify } from 'jose';

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('auth-token')?.value;

  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  try {
    const secret = new TextEncoder().encode(process.env.JWT_SECRET);
    await jwtVerify(token, secret);

    return NextResponse.next();
  } catch (error) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

export const config = {
  matcher: '/dashboard/:path*',
};

Cloudflare Workers

// worker.ts
export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);

    // Route handling
    if (url.pathname === '/api/hello') {
      return new Response(JSON.stringify({ message: 'Hello from the edge!' }), {
        headers: { 'Content-Type': 'application/json' },
      });
    }

    // Proxy to origin
    return fetch(request);
  },
};

KV Storage (Edge)

// Cloudflare KV
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const key = new URL(request.url).pathname.slice(1);

    // Get from KV
    const value = await env.MY_KV.get(key);

    if (!value) {
      return new Response('Not found', { status: 404 });
    }

    return new Response(value);
  },
};

// Set values
await env.MY_KV.put('key', 'value', {
  expirationTtl: 3600, // 1 hour
});

// Delete
await env.MY_KV.delete('key');

Edge Functions with Vercel

// app/api/edge/route.ts
import { NextRequest, NextResponse } from 'next/server';

export const runtime = 'edge';

export async function GET(request: NextRequest) {
  const data = await fetch('https://api.example.com/data', {
    headers: {
      Authorization: `Bearer ${process.env.API_KEY}`,
    },
  });

  return NextResponse.json(await data.json());
}

Rate Limiting at Edge

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

const RATE_LIMIT = 10; // requests
const WINDOW = 60000; // 1 minute

const requests = new Map<string, number[]>();

export function middleware(request: NextRequest) {
  const ip = request.ip || 'unknown';
  const now = Date.now();

  const userRequests = requests.get(ip) || [];
  const recentRequests = userRequests.filter((time) => now - time < WINDOW);

  if (recentRequests.length >= RATE_LIMIT) {
    return new NextResponse('Too many requests', { status: 429 });
  }

  recentRequests.push(now);
  requests.set(ip, recentRequests);

  return NextResponse.next();
}

Edge Caching

export async function GET(request: NextRequest) {
  const url = new URL(request.url);
  const cacheKey = url.pathname + url.search;

  // Check edge cache
  const cache = await caches.open('my-cache');
  let response = await cache.match(cacheKey);

  if (!response) {
    // Fetch from origin
    const data = await fetchData();

    response = new NextResponse(JSON.stringify(data), {
      headers: {
        'Content-Type': 'application/json',
        'Cache-Control': 's-maxage=60, stale-while-revalidate',
      },
    });

    // Store in edge cache
    await cache.put(cacheKey, response.clone());
  }

  return response;
}

Geolocation Routing

export function middleware(request: NextRequest) {
  const country = request.geo?.country;

  // Route based on country
  const countryRoutes: Record<string, string> = {
    US: '/en',
    DE: '/de',
    FR: '/fr',
    JP: '/ja',
  };

  const route = countryRoutes[country || 'US'] || '/en';

  if (!request.nextUrl.pathname.startsWith(route)) {
    return NextResponse.redirect(new URL(route, request.url));
  }

  return NextResponse.next();
}

Bot Detection

export function middleware(request: NextRequest) {
  const userAgent = request.headers.get('user-agent') || '';

  const botPatterns = [/bot/i, /crawler/i, /spider/i, /scraper/i];

  const isBot = botPatterns.some((pattern) => pattern.test(userAgent));

  if (isBot) {
    return new NextResponse('Bot detected', {
      status: 403,
      headers: {
        'X-Robots-Tag': 'noindex',
      },
    });
  }

  return NextResponse.next();
}

Feature Flags at Edge

const FEATURES: Record<string, boolean> = {
  'new-ui': true,
  'beta-feature': false,
  experimental: false,
};

export function middleware(request: NextRequest) {
  const features = Object.entries(FEATURES)
    .filter(([_, enabled]) => enabled)
    .map(([name]) => name)
    .join(',');

  const response = NextResponse.next();
  response.headers.set('x-enabled-features', features);

  return response;
}

Cloudflare Durable Objects

export class Counter {
  state: DurableObjectState;
  value: number = 0;

  constructor(state: DurableObjectState) {
    this.state = state;
    this.state.blockConcurrencyWhile(async () => {
      this.value = (await this.state.storage.get('value')) || 0;
    });
  }

  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname === '/increment') {
      this.value++;
      await this.state.storage.put('value', this.value);
    }

    return new Response(this.value.toString());
  }
}

Edge computing delivers low-latency experiences by running code close to users worldwide.

0
0
0
0