Đang tải...

Ếch Trendy

Cùng chú ếch nhỏ khám phá thế giới Web đầy biến động. Cập nhật trending nhanh như cách ếch đớp mồi! ⌨️🌿


0

Edge Computing cho web dev: Vì sao Next.js, Vercel Edge và Cloudflare Workers đang hot

Ếch Trendy
Ếch Trendy

một tháng trước · 3 phút đọc

Edge computing là gì, và tại sao mình lại quan tâm?

Mình nhớ hồi deploy cái API đầu tiên lên một server ở Singapore. Khách hàng ở Việt Nam thì ổn, nhưng ai ở Mỹ hay châu Âu ping vào là latency lên tới 300-400ms. Cảm giác như gửi thư qua bưu điện.

Edge computing sinh ra để giải quyết đúng cái vấn đề đó.

Thay vì code chạy tập trung ở một data center, edge runtime đẩy code của bạn chạy ở hàng chục, hàng trăm điểm trên toàn thế giới - gọi là edge nodes hay PoP (Points of Presence). Người dùng ở Paris kết nối tới node gần Paris nhất, người dùng ở Tokyo kết nối tới Tokyo. Không còn phải đi vòng nửa vòng Trái Đất.

346934 Request đi thẳng tới node gần nhất thay vì vòng về server trung tâm

Về mặt kỹ thuật, edge functions khác với serverless thông thường ở mấy điểm quan trọng:

  • Runtime giới hạn: Không phải Node.js đầy đủ. Cloudflare Workers dùng V8 isolates, Vercel Edge dùng Edge Runtime - một subset của Web APIs.
  • Cold start gần như bằng 0: V8 isolates khởi động trong microseconds, không phải hàng trăm milliseconds như Lambda.
  • Không có filesystem: Không đọc file được. Mọi thứ phải in-memory hoặc từ external storage.
  • Giới hạn CPU time: Thường 50ms CPU time per request, không phải wall-clock time.

Khi nào nên dùng edge, khi nào thì không

Đây là câu hỏi mình thấy nhiều dev bỏ qua nhất. Edge không phải silver bullet.

346935 Chọn đúng tool đúng bài toán - edge không phải lúc nào cũng là đáp án

Nên dùng edge khi:

  • Latency-sensitive: A/B testing, personalization header, geolocation redirect. Những thứ cần quyết định trong <10ms trước khi serve content.
  • Auth middleware: Kiểm tra JWT token, redirect nếu chưa login - không cần gọi về origin server.
  • Bot detection và rate limiting: Chặn ngay tại edge trước khi request chạm tới app.
  • Response transformation: Thêm/bớt header, rewrite URL, compress response.
  • Caching logic phức tạp: Quyết định cache key dựa trên cookie, header, hay geo.

Không nên dùng edge khi:

  • Heavy database queries: Edge không có persistent connection tới PostgreSQL hay MySQL. Mỗi request phải mở connection mới - cực kỳ tốn kém về latency.
  • CPU-intensive tasks: Video encoding, image processing, ML inference - edge có giới hạn CPU time nghiêm ngặt.
  • Complex business logic: Nếu logic cần gọi 5-6 services khác nhau, latency gain từ edge sẽ bị nuốt hết bởi các roundtrips đó.
  • File system operations: Edge runtime không có filesystem. Cần đọc file? Dùng Lambda hoặc container.

Một cái rule of thumb mình hay dùng: nếu function của bạn chạy xong trong <5ms và không cần external I/O, edge là perfect fit. Nếu cần I/O - cân nhắc kỹ.


Vercel Edge Functions và Next.js middleware

Nếu bạn đang dùng Next.js, edge runtime gần như đã có sẵn trong tay. Không cần setup gì thêm.

Next.js middleware chạy trên Vercel Edge Network - tức là mọi request vào app của bạn đều đi qua middleware trước khi tới server. Đây là cách viết một middleware đơn giản:

// middleware.ts - chạy ở edge, không phải server
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  // Lấy token từ cookie
  const token = request.cookies.get('auth-token')?.value;

  // Redirect về login nếu chưa auth
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // Thêm header geo để component có thể dùng
  const response = NextResponse.next();
  response.headers.set('x-user-country', request.geo?.country ?? 'unknown');

  return response;
}

// Chỉ chạy middleware cho các route này
export const config = {
  matcher: ['/dashboard/:path*', '/api/:path*'],
};

346936 Middleware chặn request tại edge - không một request nào lọt vào server nếu chưa qua kiểm tra

Vercel Edge Functions thì tương tự nhưng là API route chạy ở edge:

// app/api/hello/route.ts
import { NextResponse } from 'next/server';

export const runtime = 'edge'; // Khai báo dùng edge runtime

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

  return NextResponse.json({
    message: `Hello, ${name}!`,
    // Geo data có sẵn qua header từ Vercel
    region: request.headers.get('x-vercel-ip-country'),
  });
}

Một điểm cần nhớ: khi dùng runtime = 'edge', bạn không thể dùng các Node.js APIs như fs, path, hay nhiều npm packages dựa vào Node internals. Nếu package không hỗ trợ edge runtime, build sẽ fail. Kiểm tra trước bằng danh sách APIs hỗ trợ Edge Runtime của Next.js.


Cloudflare Workers: linh hoạt hơn, nhưng cần setup nhiều hơn

Nếu Vercel Edge là "pin và xài", Cloudflare Workers là "tự lắp theo ý muốn". Không ràng buộc với framework nào, chạy được độc lập.

Workers dùng V8 isolates - không phải container, không phải VM. Mỗi request chạy trong một isolate riêng, cold start dưới 1ms. Đây là lý do Workers nhanh hơn Lambda đáng kể về startup time.

// worker.js - Cloudflare Worker cơ bản
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Route cơ bản
    if (url.pathname === '/api/hello') {
      return new Response(
        JSON.stringify({ message: 'Hello from edge!' }),
        {
          headers: {
            'Content-Type': 'application/json',
            // Cache response 60 giây tại edge
            'Cache-Control': 'public, max-age=60',
          },
        }
      );
    }

    // Proxy request về origin nếu không match
    return fetch(request);
  },
};

346937 Cloudflare Workers chạy trên hơn 300 data centers toàn cầu - gần như không có điểm nào trên Trái Đất xa quá 50ms

Cloudflare còn có KV Storage (key-value store), R2 (object storage giống S3), và Durable Objects (stateful workers). Đây là những thứ mà Vercel Edge không có, khiến Workers phù hợp hơn cho use case phức tạp hơn.

So sánh nhanh Vercel Edge vs Cloudflare Workers:

Vercel Edge Cloudflare Workers
Tích hợp Next.js Native Cần adapter
Cold start ~0ms ~0ms
CPU time limit 50ms 10ms (free) / 30s (paid)
Storage Vercel KV KV, R2, Durable Objects
Pricing Theo plan 100k req/day free
PoP count 126+ points of presence across 51 countries (2024) (Vercel Official Documentation) 330+ data centers / PoPs in 2024-2025 (Cloudflare Official Network Information)

Nếu bạn đang build trên Next.js và không cần gì quá phức tạp, Vercel Edge là lựa chọn ma sát thấp nhất. Nếu cần stateful workers, phức tạp hơn, hoặc không muốn vendor lock-in vào Vercel, Workers là đáp án.


Caching strategies tại edge

Edge không chỉ để chạy logic - caching tại edge mới là thứ giúp app bạn scale mà không tốn tiền server.

Có 3 pattern mình hay dùng:

1. Cache-Control headers - đơn giản nhất:

// Cache response 1 tiếng tại edge, stale-while-revalidate 24 tiếng
return new Response(data, {
  headers: {
    'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
  },
});

stale-while-revalidate là key ở đây. Edge serve stale cache ngay lập tức, đồng thời revalidate trong background. Người dùng không bao giờ thấy loading.

2. Cache API - cache thủ công trong Workers:

export default {
  async fetch(request, env, ctx) {
    const cache = caches.default;
    const cacheKey = new Request(request.url);

    // Kiểm tra cache trước
    let response = await cache.match(cacheKey);
    if (response) return response;

    // Fetch từ origin nếu chưa có cache
    response = await fetch(request);

    // Clone response vì body chỉ đọc được 1 lần
    const responseToCache = response.clone();

    // Lưu vào cache không block response trả về
    ctx.waitUntil(cache.put(cacheKey, responseToCache));

    return response;
  },
};

3. Stale cache + background refresh với KV:

async function getWithStaleWhileRevalidate(env, key, fetcher) {
  const cached = await env.KV.get(key, { type: 'json' });

  if (cached && Date.now() - cached.timestamp < 60_000) {
    // Còn fresh, trả về luôn
    return cached.data;
  }

  if (cached) {
    // Stale nhưng có cache, trả về và refresh nền
    // ctx.waitUntil() gọi ở ngoài để không block response
    return cached.data;
  }

  // Không có cache, fetch mới
  const data = await fetcher();
  await env.KV.put(key, JSON.stringify({ data, timestamp: Date.now() }));
  return data;
}

346938 Stale-while-revalidate là trick đơn giản nhất để cache mà không làm UX tệ đi

Một lưu ý về cache invalidation: đây vẫn là bài toán khó nhất trong distributed systems. Edge cache không có cách purge instant hoàn toàn (dù Cloudflare có Cache Purge API). Thiết kế cache key cẩn thận từ đầu quan trọng hơn nhiều so với việc tìm cách invalidate sau.


Cold start, cost model và monitoring

Ba thứ này hay bị bỏ qua khi mới bắt đầu với edge - rồi sau đó bật ngửa khi bill về.

Cold start tại edge

Như mình đã nói, V8 isolates không có cold start đáng kể. Nhưng Vercel Edge Functions có một khái niệm khác: region warm-up. Lần đầu request vào một region chưa từng có traffic, function phải được load vào memory của node đó. Thường dưới 100ms, nhưng vẫn là thứ cần biết.

Optimization đơn giản: giữ bundle size nhỏ. Edge runtime parse JavaScript mỗi lần load, bundle nhỏ = warm-up nhanh hơn.

// ❌ Import cả lodash vào edge function là ý tưởng tệ
import _ from 'lodash'; // ~70KB

// ✅ Chỉ import function cần dùng, hoặc tự viết
const chunk = (arr, size) =>
  Array.from({ length: Math.ceil(arr.length / size) },
    (_, i) => arr.slice(i * size, (i + 1) * size));

Cost model

Cloudflare Workers free tier: 100,000 requests/ngày, 10ms CPU time/request. Workers Paid: $5/tháng cho 10 triệu requests.

Vercel tính theo plan - Edge Function invocations được tính khác với Serverless Function invocations. Đọc kỹ pricing trước khi ship production.

Monitoring

346939 Log tại edge phân tán hơn - cần tooling riêng để aggregate

Monitoring edge functions khó hơn Lambda vì log phân tán ở nhiều regions. Các option:

  • Cloudflare Analytics + Logpush: Push log về R2 hoặc third-party (Datadog, Splunk)
  • Vercel Analytics: Built-in, nhưng basic
  • OpenTelemetry: Instrument code, push traces về Honeycomb hay Grafana Tempo
// Logging pattern đơn giản cho Cloudflare Workers
export default {
  async fetch(request, env, ctx) {
    const start = Date.now();
    const requestId = crypto.randomUUID();

    try {
      const response = await handleRequest(request, env);

      // Log sau khi response đã trả về
      ctx.waitUntil(logRequest(env, {
        requestId,
        duration: Date.now() - start,
        status: response.status,
        country: request.cf?.country,
        url: request.url,
      }));

      return response;
    } catch (err) {
      // Log error không block response lỗi
      ctx.waitUntil(logError(env, { requestId, error: err.message }));
      return new Response('Internal Error', { status: 500 });
    }
  },
};

ctx.waitUntil() là pattern quan trọng: cho phép bạn làm async work sau khi response đã được gửi về client. Dùng cho logging, analytics, cache warming - bất cứ thứ gì không cần block response.

Trang web dùng cookie để hoạt động và đo hiệu quả quảng cáo. Xem chính sách bảo mật