Langkau ke kandungan
THE GUILD
0%
Perkhidmatan Produk Kerjaya Tentang Kami Blog Soalan Lazim Hubungi Kami
Edge Computing untuk Pembangun Frontend: Panduan Lengkap 2026

Edge computing telah berubah daripada kebimbangan infrastruktur kepada kemahiran pembangunan frontend yang kritikal. Pada 2026, garis antara frontend dan backend terus kabur apabila pembangun menggunakan kod yang berjalan dalam milisaat daripada pengguna di seluruh dunia. Panduan komprehensif ini merangkumi semua yang pembangun frontend perlu tahu tentang edge computing—daripada konsep asas hingga pelaksanaan sedia produksi.

Sama ada anda mengoptimumkan aplikasi sedia ada atau mereka bentuk sistem baharu, memahami edge computing adalah penting untuk membina aplikasi web moden yang berprestasi tinggi.

Apakah Edge Computing untuk Pembangun Frontend?

Edge computing membawa pengkomputeran dan penyimpanan data lebih dekat kepada sumber data. Untuk pembangun frontend, ini bermakna menjalankan logik sisi pelayan pada pelayan teragih yang terletak berdekatan dengan pengguna, bukannya di pusat data berpusat.

Seni Bina Tradisional vs Seni Bina Edge

Seni Bina Tradisional:

Pengguna di Tokyo → CDN (fail statik) → Pelayan Asal di Virginia → Pangkalan Data

                              Kependaman 500ms+

Seni Bina Edge:

Pengguna di Tokyo → Pelayan Edge di Tokyo → Asal (jika perlu)

               Kependaman 50ms
               (Kandungan dinamik dirender di edge)

Mengapa Pembangun Frontend Memerlukan Kemahiran Edge

Evolusi platform web telah mengubah secara fundamental apa yang dimaksudkan dengan “frontend”:

  1. Komponen Pelayan: React Server Components, Astro, dan teknologi serupa mengaburkan sempadan klien-pelayan
  2. Rendering Edge: SSR dan SSG di edge untuk kandungan dinamik yang diperibadikan
  3. Laluan API: Rangka kerja frontend kini termasuk keupayaan backend
  4. Ciri Masa Nyata: Penyelesaian edge-native untuk WebSocket dan penstriman

Platform Edge: Panduan Pembangun Frontend

Pelbagai platform menawarkan keupayaan edge computing. Memahami kekuatan masing-masing membantu anda memilih alat yang betul.

Vercel Edge Functions

Vercel Edge Functions berjalan pada Rangkaian Edge Vercel, dikuasakan oleh isolat V8. Ideal untuk aplikasi Next.js.

Ciri Utama:

  • Cold start sub-milisaat
  • Respons penstriman
  • Penggunaan global secara lalai
  • Integrasi native Next.js

Fungsi Edge Asas:

// app/api/hello/route.ts
export const runtime = 'edge';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const name = searchParams.get('name') || 'World';

  return new Response(`Hello, ${name}!`, {
    headers: {
      'content-type': 'text/plain',
    },
  });
}

Middleware Edge:

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

export function middleware(request: NextRequest) {
  // Get user's country from edge
  const country = request.geo?.country || 'US';

  // Personalize based on location
  const response = NextResponse.next();
  response.headers.set('x-user-country', country);

  // A/B testing at the edge
  const bucket = Math.random() < 0.5 ? 'control' : 'experiment';
  response.cookies.set('ab-bucket', bucket);

  return response;
}

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

Cloudflare Workers

Cloudflare Workers menyediakan platform edge computing paling matang dengan API yang luas.

Ciri Utama:

  • 200+ lokasi edge di seluruh dunia
  • Storan KV untuk data edge
  • Durable Objects untuk aplikasi berkeadaan
  • Workers AI untuk pembelajaran mesin di edge

Worker Asas:

// src/index.js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    if (url.pathname === '/api/data') {
      // Fetch from KV store at the edge
      const cachedData = await env.MY_KV.get('data-key', 'json');

      if (cachedData) {
        return Response.json(cachedData);
      }

      // Fetch from origin and cache
      const response = await fetch('https://api.origin.com/data');
      const data = await response.json();

      // Cache for 1 hour
      ctx.waitUntil(env.MY_KV.put('data-key', JSON.stringify(data), {
        expirationTtl: 3600
      }));

      return Response.json(data);
    }

    return new Response('Not Found', { status: 404 });
  }
};

Konfigurasi Wrangler:

# wrangler.toml
name = "my-edge-app"
main = "src/index.js"
compatibility_date = "2026-01-01"

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

[vars]
ENVIRONMENT = "production"

Deno Deploy

Deno Deploy menawarkan edge computing dengan sokongan TypeScript kelas pertama dan API Standard Web.

Ciri Utama:

  • TypeScript sedia digunakan
  • API standard web
  • Pangkalan data KV terbina dalam
  • Integrasi GitHub

Fungsi Edge Deno:

// main.ts
import { serve } from "https://deno.land/[email protected]/http/server.ts";

const kv = await Deno.openKv();

serve(async (request: Request) => {
  const url = new URL(request.url);

  if (url.pathname === "/api/counter") {
    // Atomic increment at the edge
    const key = ["counters", "visits"];
    const result = await kv.atomic()
      .sum(key, 1n)
      .commit();

    const entry = await kv.get(key);

    return Response.json({
      count: entry.value?.toString() || "0"
    });
  }

  return new Response("Hello from the Edge!");
}, { port: 8000 });

AWS CloudFront Functions & Lambda@Edge

AWS menawarkan dua pilihan edge computing dengan keupayaan berbeza.

CloudFront Functions (ringan):

function handler(event) {
  var request = event.request;
  var headers = request.headers;

  // Add security headers at the edge
  var response = {
    statusCode: 200,
    statusDescription: 'OK',
    headers: {
      'strict-transport-security': { value: 'max-age=31536000' },
      'content-security-policy': { value: "default-src 'self'" },
      'x-content-type-options': { value: 'nosniff' },
      'x-frame-options': { value: 'DENY' }
    }
  };

  return response;
}

Lambda@Edge (pengkomputeran penuh):

exports.handler = async (event) => {
  const request = event.Records[0].cf.request;

  // Personalization at the edge
  const userAgent = request.headers['user-agent'][0].value;
  const isMobile = /Mobile|Android/.test(userAgent);

  if (isMobile) {
    request.uri = request.uri.replace(/\.html$/, '.mobile.html');
  }

  return request;
};

Corak Edge Computing Biasa

Pembangun frontend kerap melaksanakan corak-corak ini di edge.

Corak 1: Pemperibadian di Edge

Hantar kandungan diperibadikan tanpa perjalanan pergi balik ke asal:

// Vercel Edge Middleware for personalization
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export async function middleware(request: NextRequest) {
  const response = NextResponse.next();

  // Get personalization context
  const country = request.geo?.country || 'US';
  const city = request.geo?.city || 'Unknown';
  const userAgent = request.headers.get('user-agent') || '';

  // Determine content variant
  const isMobile = /Mobile|Android|iPhone/.test(userAgent);
  const locale = getPreferredLocale(request.headers.get('accept-language'));
  const currency = getCurrencyForCountry(country);

  // Set headers for downstream use
  response.headers.set('x-personalization', JSON.stringify({
    country,
    city,
    isMobile,
    locale,
    currency
  }));

  // Rewrite to personalized content
  if (request.nextUrl.pathname === '/') {
    return NextResponse.rewrite(
      new URL(`/${locale}/home?currency=${currency}`, request.url),
      { headers: response.headers }
    );
  }

  return response;
}

function getPreferredLocale(acceptLanguage: string | null): string {
  if (!acceptLanguage) return 'en';

  const locales = ['en', 'ja', 'de', 'fr', 'es', 'zh'];
  const preferred = acceptLanguage.split(',')[0].split('-')[0];

  return locales.includes(preferred) ? preferred : 'en';
}

function getCurrencyForCountry(country: string): string {
  const currencyMap: Record<string, string> = {
    US: 'USD',
    JP: 'JPY',
    GB: 'GBP',
    DE: 'EUR',
    MY: 'MYR'
  };

  return currencyMap[country] || 'USD';
}

Corak 2: Ujian A/B di Edge

Laksanakan ujian A/B yang konsisten tanpa kelipan sisi klien:

// Cloudflare Worker for A/B testing
interface Env {
  EXPERIMENTS_KV: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // Get or assign experiment bucket
    const cookies = parseCookies(request.headers.get('cookie'));
    let bucket = cookies['ab-experiment'];

    if (!bucket) {
      // Assign new user to experiment
      const experiment = await env.EXPERIMENTS_KV.get('homepage-v2', 'json') as {
        variants: { id: string; weight: number }[];
      };

      bucket = assignVariant(experiment.variants);
    }

    // Rewrite to experiment variant
    if (url.pathname === '/') {
      const variantUrl = new URL(url);
      variantUrl.pathname = `/experiments/${bucket}/index.html`;

      const response = await fetch(variantUrl);
      const modifiedResponse = new Response(response.body, response);

      // Set cookie for consistent experience
      modifiedResponse.headers.append(
        'Set-Cookie',
        `ab-experiment=${bucket}; Path=/; Max-Age=2592000; SameSite=Lax`
      );

      // Track assignment for analytics
      await trackExperimentAssignment(bucket, request);

      return modifiedResponse;
    }

    return fetch(request);
  }
};

function assignVariant(variants: { id: string; weight: number }[]): string {
  const random = Math.random();
  let cumulative = 0;

  for (const variant of variants) {
    cumulative += variant.weight;
    if (random < cumulative) {
      return variant.id;
    }
  }

  return variants[0].id;
}

Corak 3: Edge-Side Includes (ESI)

Gabungkan halaman daripada serpihan yang di-cache di edge:

// Edge function for ESI-style composition
export async function onRequest(context: EventContext) {
  const url = new URL(context.request.url);

  if (url.pathname.startsWith('/product/')) {
    // Fetch page components in parallel
    const [header, productContent, recommendations, footer] = await Promise.all([
      fetchCachedFragment('/fragments/header'),
      fetchProductContent(url.pathname),
      fetchPersonalizedRecommendations(context.request),
      fetchCachedFragment('/fragments/footer')
    ]);

    // Compose final HTML
    const html = `
      <!DOCTYPE html>
      <html>
        <head>
          <title>${productContent.title}</title>
        </head>
        <body>
          ${header}
          <main>${productContent.html}</main>
          <aside>${recommendations}</aside>
          ${footer}
        </body>
      </html>
    `;

    return new Response(html, {
      headers: {
        'content-type': 'text/html',
        'cache-control': 'public, max-age=60, stale-while-revalidate=300'
      }
    });
  }

  return context.next();
}

async function fetchCachedFragment(path: string): Promise<string> {
  // Fragments cached at edge for 1 hour
  const response = await fetch(`https://origin.com${path}`, {
    cf: { cacheTtl: 3600 }
  });
  return response.text();
}

async function fetchPersonalizedRecommendations(request: Request): Promise<string> {
  // Personalized content based on cookies/geo
  const userId = getCookie(request, 'user_id');
  const country = request.cf?.country || 'US';

  const response = await fetch(
    `https://api.origin.com/recommendations?user=${userId}&country=${country}`
  );
  const data = await response.json();

  return renderRecommendations(data);
}

Corak 4: Pengesahan Edge

Sahkan pengesahan di edge sebelum permintaan mencapai asal:

// JWT validation at the edge
import { jwtVerify } from 'jose';

interface Env {
  JWT_SECRET: string;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    // Skip auth for public routes
    if (isPublicRoute(url.pathname)) {
      return fetch(request);
    }

    // Extract and validate JWT
    const authHeader = request.headers.get('authorization');

    if (!authHeader?.startsWith('Bearer ')) {
      return new Response('Unauthorized', { status: 401 });
    }

    const token = authHeader.slice(7);

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

      // Add user context to request
      const modifiedHeaders = new Headers(request.headers);
      modifiedHeaders.set('x-user-id', payload.sub as string);
      modifiedHeaders.set('x-user-role', payload.role as string);

      const modifiedRequest = new Request(request, {
        headers: modifiedHeaders
      });

      return fetch(modifiedRequest);
    } catch (error) {
      return new Response('Invalid token', { status: 401 });
    }
  }
};

function isPublicRoute(pathname: string): boolean {
  const publicRoutes = ['/login', '/register', '/api/health', '/public'];
  return publicRoutes.some(route => pathname.startsWith(route));
}

Corak 5: Caching Pintar dengan Stale-While-Revalidate

Laksanakan strategi caching pintar di edge:

// Cloudflare Worker with smart caching
interface Env {
  CACHE_KV: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const cacheKey = new URL(request.url).pathname;

    // Try to get from edge cache
    const cached = await env.CACHE_KV.getWithMetadata(cacheKey, 'json');

    if (cached.value) {
      const metadata = cached.metadata as { expires: number; stale: number };
      const now = Date.now();

      if (now < metadata.expires) {
        // Fresh cache hit
        return Response.json(cached.value, {
          headers: { 'x-cache': 'HIT' }
        });
      }

      if (now < metadata.stale) {
        // Stale-while-revalidate
        ctx.waitUntil(revalidateCache(request, env, cacheKey));

        return Response.json(cached.value, {
          headers: { 'x-cache': 'STALE' }
        });
      }
    }

    // Cache miss - fetch from origin
    return revalidateCache(request, env, cacheKey);
  }
};

async function revalidateCache(
  request: Request,
  env: Env,
  cacheKey: string
): Promise<Response> {
  const response = await fetch(`https://api.origin.com${cacheKey}`);
  const data = await response.json();

  // Store with TTL metadata
  const now = Date.now();
  await env.CACHE_KV.put(cacheKey, JSON.stringify(data), {
    metadata: {
      expires: now + 60000,      // Fresh for 1 minute
      stale: now + 300000        // Stale for 5 minutes
    }
  });

  return Response.json(data, {
    headers: { 'x-cache': 'MISS' }
  });
}

Storan Data Edge

Edge computing memerlukan penyelesaian storan data yang asli-edge.

Cloudflare KV

Storan kunci-nilai yang dioptimumkan untuk beban kerja berat-bacaan:

// KV operations at the edge
interface Env {
  USER_PREFERENCES: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    const userId = url.searchParams.get('userId');

    if (request.method === 'GET') {
      // Read user preferences
      const prefs = await env.USER_PREFERENCES.get(`user:${userId}`, 'json');
      return Response.json(prefs || { theme: 'light', language: 'en' });
    }

    if (request.method === 'POST') {
      // Update preferences
      const body = await request.json();

      await env.USER_PREFERENCES.put(`user:${userId}`, JSON.stringify(body), {
        expirationTtl: 86400 * 30  // 30 days
      });

      return Response.json({ success: true });
    }

    return new Response('Method not allowed', { status: 405 });
  }
};

Cloudflare Durable Objects

Pengkomputeran berkeadaan di edge untuk aplikasi masa nyata:

// Durable Object for real-time collaboration
export class DocumentRoom {
  state: DurableObjectState;
  sessions: Map<WebSocket, { userId: string }>;
  document: string;

  constructor(state: DurableObjectState) {
    this.state = state;
    this.sessions = new Map();
    this.document = '';
  }

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

    if (url.pathname === '/websocket') {
      // Handle WebSocket upgrade
      const pair = new WebSocketPair();
      const [client, server] = Object.values(pair);

      const userId = url.searchParams.get('userId') || 'anonymous';
      this.handleSession(server, userId);

      return new Response(null, { status: 101, webSocket: client });
    }

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

  handleSession(webSocket: WebSocket, userId: string) {
    webSocket.accept();
    this.sessions.set(webSocket, { userId });

    // Send current document state
    webSocket.send(JSON.stringify({
      type: 'sync',
      document: this.document,
      users: Array.from(this.sessions.values()).map(s => s.userId)
    }));

    webSocket.addEventListener('message', (event) => {
      const message = JSON.parse(event.data as string);

      if (message.type === 'edit') {
        // Apply edit and broadcast
        this.document = applyEdit(this.document, message.edit);

        this.broadcast({
          type: 'edit',
          userId,
          edit: message.edit
        }, webSocket);
      }
    });

    webSocket.addEventListener('close', () => {
      this.sessions.delete(webSocket);
      this.broadcast({ type: 'user_left', userId });
    });
  }

  broadcast(message: object, exclude?: WebSocket) {
    const json = JSON.stringify(message);

    for (const [ws] of this.sessions) {
      if (ws !== exclude) {
        ws.send(json);
      }
    }
  }
}

Deno KV

Pangkalan data kunci-nilai terbina dalam untuk Deno Deploy:

// Deno KV for edge data
const kv = await Deno.openKv();

// Atomic transactions
async function transferBalance(fromId: string, toId: string, amount: number) {
  const fromKey = ["balances", fromId];
  const toKey = ["balances", toId];

  // Atomic check-and-update
  let success = false;

  while (!success) {
    const fromEntry = await kv.get<number>(fromKey);
    const toEntry = await kv.get<number>(toKey);

    const fromBalance = fromEntry.value || 0;
    const toBalance = toEntry.value || 0;

    if (fromBalance < amount) {
      throw new Error("Insufficient balance");
    }

    const result = await kv.atomic()
      .check(fromEntry)
      .check(toEntry)
      .set(fromKey, fromBalance - amount)
      .set(toKey, toBalance + amount)
      .commit();

    success = result.ok;
  }

  return { success: true };
}

// Secondary indexes
async function addUser(user: { id: string; email: string; name: string }) {
  await kv.atomic()
    .set(["users", user.id], user)
    .set(["users_by_email", user.email], user.id)
    .commit();
}

async function getUserByEmail(email: string) {
  const idEntry = await kv.get<string>(["users_by_email", email]);
  if (!idEntry.value) return null;

  const userEntry = await kv.get(["users", idEntry.value]);
  return userEntry.value;
}

Pengoptimuman Prestasi di Edge

Maksimumkan manfaat edge computing dengan teknik pengoptimuman berikut.

Respons Penstriman

Strim kandungan semasa ia dijana:

// Streaming response from edge
export async function onRequest(context: EventContext): Promise<Response> {
  const { readable, writable } = new TransformStream();
  const writer = writable.getWriter();
  const encoder = new TextEncoder();

  // Start streaming immediately
  context.waitUntil((async () => {
    // Write HTML head immediately
    await writer.write(encoder.encode(`
      <!DOCTYPE html>
      <html>
        <head><title>Streaming Page</title></head>
        <body>
          <header>Loading content...</header>
    `));

    // Stream main content as it becomes available
    const mainContent = await fetchMainContent();
    await writer.write(encoder.encode(`
          <main>${mainContent}</main>
    `));

    // Stream sidebar
    const sidebarContent = await fetchSidebarContent();
    await writer.write(encoder.encode(`
          <aside>${sidebarContent}</aside>
    `));

    // Complete the page
    await writer.write(encoder.encode(`
        </body>
      </html>
    `));

    await writer.close();
  })());

  return new Response(readable, {
    headers: { 'content-type': 'text/html' }
  });
}

Penggabungan Permintaan

Elakkan “thundering herd” pada cache miss:

// Request coalescing at the edge
const inflightRequests = new Map<string, Promise<Response>>();

export async function onRequest(context: EventContext): Promise<Response> {
  const cacheKey = context.request.url;

  // Check if request is already in-flight
  const inflight = inflightRequests.get(cacheKey);
  if (inflight) {
    // Wait for existing request
    const response = await inflight;
    return response.clone();
  }

  // Make new request and store promise
  const fetchPromise = fetchWithCache(context.request);
  inflightRequests.set(cacheKey, fetchPromise);

  try {
    const response = await fetchPromise;
    return response;
  } finally {
    // Clean up after completion
    inflightRequests.delete(cacheKey);
  }
}

async function fetchWithCache(request: Request): Promise<Response> {
  const cache = caches.default;

  let response = await cache.match(request);

  if (!response) {
    response = await fetch(request);

    // Cache successful responses
    if (response.ok) {
      const cloned = response.clone();
      cloned.headers.set('Cache-Control', 'public, max-age=60');
      await cache.put(request, cloned);
    }
  }

  return response;
}

Imej Dioptimumkan Edge

Ubah dan optimumkan imej di edge:

// Image optimization at the edge
export async function onRequest(context: EventContext): Promise<Response> {
  const url = new URL(context.request.url);

  if (!url.pathname.startsWith('/images/')) {
    return context.next();
  }

  // Parse optimization parameters
  const width = parseInt(url.searchParams.get('w') || '0');
  const quality = parseInt(url.searchParams.get('q') || '80');
  const format = url.searchParams.get('f') || 'auto';

  // Determine best format based on Accept header
  const accept = context.request.headers.get('accept') || '';
  const outputFormat = format === 'auto'
    ? accept.includes('image/avif') ? 'avif'
    : accept.includes('image/webp') ? 'webp'
    : 'jpeg'
    : format;

  // Use Cloudflare Image Resizing
  const imageUrl = `https://origin.com${url.pathname}`;

  const response = await fetch(imageUrl, {
    cf: {
      image: {
        width: width || undefined,
        quality,
        format: outputFormat
      }
    }
  });

  // Add cache headers
  const headers = new Headers(response.headers);
  headers.set('Cache-Control', 'public, max-age=31536000, immutable');
  headers.set('Vary', 'Accept');

  return new Response(response.body, {
    status: response.status,
    headers
  });
}

Menguji Fungsi Edge

Strategi pengujian komprehensif untuk kod edge.

Pembangunan Tempatan

Jalankan fungsi edge secara tempatan:

// Miniflare for local Cloudflare Workers testing
import { Miniflare } from 'miniflare';

const mf = new Miniflare({
  script: `
    export default {
      async fetch(request, env) {
        return new Response('Hello from edge!');
      }
    }
  `,
  modules: true,
  kvNamespaces: ['MY_KV'],
});

const response = await mf.dispatchFetch('http://localhost/');
console.log(await response.text()); // "Hello from edge!"

Ujian Unit

Uji fungsi edge secara terasing:

// Jest tests for edge functions
import { unstable_dev } from 'wrangler';

describe('Edge API', () => {
  let worker: any;

  beforeAll(async () => {
    worker = await unstable_dev('src/index.ts', {
      experimental: { disableExperimentalWarning: true }
    });
  });

  afterAll(async () => {
    await worker.stop();
  });

  test('returns personalized greeting', async () => {
    const response = await worker.fetch('/api/greet?name=World');
    const text = await response.text();

    expect(response.status).toBe(200);
    expect(text).toBe('Hello, World!');
  });

  test('handles missing parameters', async () => {
    const response = await worker.fetch('/api/greet');
    const text = await response.text();

    expect(text).toBe('Hello, Guest!');
  });
});

Ujian Integrasi

Uji fungsi edge dengan kebergantungan sebenar:

// Integration tests with KV storage
describe('Edge Cache', () => {
  let mf: Miniflare;
  let kv: any;

  beforeEach(async () => {
    mf = new Miniflare({
      scriptPath: './src/index.ts',
      modules: true,
      kvNamespaces: ['CACHE']
    });

    kv = await mf.getKVNamespace('CACHE');
  });

  test('caches API responses', async () => {
    // First request - cache miss
    const response1 = await mf.dispatchFetch('http://localhost/api/data');
    expect(response1.headers.get('x-cache')).toBe('MISS');

    // Second request - cache hit
    const response2 = await mf.dispatchFetch('http://localhost/api/data');
    expect(response2.headers.get('x-cache')).toBe('HIT');

    // Verify data is in KV
    const cached = await kv.get('/api/data', 'json');
    expect(cached).toBeDefined();
  });
});

Pertimbangan Keselamatan

Edge computing memperkenalkan cabaran keselamatan yang unik.

Pengesahan Input di Edge

Sahkan dan bersihkan semua input:

// Input validation middleware
export async function middleware(request: NextRequest) {
  const url = new URL(request.url);

  // Validate query parameters
  for (const [key, value] of url.searchParams) {
    if (!isValidParameter(key, value)) {
      return new Response('Bad Request', { status: 400 });
    }
  }

  // Validate request body for POST/PUT
  if (['POST', 'PUT', 'PATCH'].includes(request.method)) {
    try {
      const body = await request.json();

      if (!validateRequestBody(body)) {
        return new Response('Invalid request body', { status: 400 });
      }
    } catch {
      return new Response('Invalid JSON', { status: 400 });
    }
  }

  return NextResponse.next();
}

function isValidParameter(key: string, value: string): boolean {
  // Length limits
  if (key.length > 64 || value.length > 1024) return false;

  // Character validation
  if (!/^[\w-]+$/.test(key)) return false;

  // SQL injection patterns
  const sqlPatterns = /('|"|;|--|\b(SELECT|INSERT|UPDATE|DELETE|DROP)\b)/i;
  if (sqlPatterns.test(value)) return false;

  return true;
}

Had Kadar

Laksanakan had kadar di edge:

// Edge rate limiting with Cloudflare KV
interface Env {
  RATE_LIMITS: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const clientIP = request.headers.get('cf-connecting-ip') || 'unknown';
    const windowKey = `ratelimit:${clientIP}:${Math.floor(Date.now() / 60000)}`;

    // Get current count
    const current = await env.RATE_LIMITS.get(windowKey);
    const count = current ? parseInt(current) : 0;

    // Check limit (100 requests per minute)
    if (count >= 100) {
      return new Response('Rate limit exceeded', {
        status: 429,
        headers: {
          'Retry-After': '60',
          'X-RateLimit-Limit': '100',
          'X-RateLimit-Remaining': '0'
        }
      });
    }

    // Increment counter
    await env.RATE_LIMITS.put(windowKey, String(count + 1), {
      expirationTtl: 120  // 2 minute TTL
    });

    // Process request
    const response = await fetch(request);
    const modifiedResponse = new Response(response.body, response);

    modifiedResponse.headers.set('X-RateLimit-Limit', '100');
    modifiedResponse.headers.set('X-RateLimit-Remaining', String(99 - count));

    return modifiedResponse;
  }
};

Kesimpulan: Menerima Pembangunan Edge-First

Edge computing mewakili masa depan pembangunan web. Apabila aplikasi menuntut kependaman yang lebih rendah, pemperibadian yang lebih tinggi, dan jangkauan global, edge computing menyediakan seni bina untuk menyampaikan pengalaman pengguna yang luar biasa.

Pengambilan Utama

  1. Pilih platform yang betul: Vercel untuk Next.js, Cloudflare untuk beban kerja kompleks, Deno untuk pembangunan TypeScript-first
  2. Fikir edge-first: Reka bentuk aplikasi dengan pengkomputeran edge dalam fikiran dari awal
  3. Manfaatkan data edge: Gunakan stor KV dan Durable Objects untuk aplikasi edge stateful
  4. Optimumkan untuk penstriman: Strim respons untuk meningkatkan prestasi yang dirasai
  5. Uji dengan teliti: Pembangunan tempatan dan ujian integrasi adalah penting

Masa Depan Edge Computing

Semasa kita melalui 2026, edge computing akan terus berkembang:

  • AI di edge: Inferens pembelajaran mesin berjalan pada nod edge
  • Pengembangan WebAssembly: Lebih banyak bahasa dikompil untuk berjalan pada platform edge
  • Integrasi lebih mendalam: Gandingan lebih rapat antara rangka kerja frontend dan masa jalan edge

Perlukan Kepakaran Pembangunan Edge?

Membina aplikasi edge-native memerlukan pengetahuan khusus tentang sistem teragih, pengoptimuman prestasi, dan seni bina web moden. Pasukan pembangunan luar pesisir kami pakar dalam membina aplikasi web berprestasi tinggi menggunakan teknologi edge computing.

Terokai Pembangunan Sistem Web Ketahui Tentang Pembangunan SaaS


Bersedia untuk membawa aplikasi anda ke edge? Masa depan prestasi web adalah teragih.

Cabaran edge computing apakah yang anda hadapi? Kongsikan pengalaman dan soalan anda.


Sumber: