Edge Computing × Frontend: Deixe Seu Site Ultra-rápido com Cloudflare Workers/Vercel Edge
Por que o Frontend Precisa de Edge Computing?
Em arquiteturas tradicionais, as requisições dos usuários precisam atravessar metade da internet para chegar aos servidores de origem:
Usuário (Tóquio) → Nó CDN (Tóquio, apenas cache estático) → Origem (EUA Oeste, computação dinâmica)
Latência: ~10ms ~150ms cruzando o Pacífico ~50ms computação
Total: ~210ms
A computação de borda leva a lógica de computação para o nó mais próximo do usuário:
Usuário (Tóquio) → Nó Edge (Tóquio, computação direta)
Latência: ~10ms ~5ms computação local
Total: ~15ms
14x menos latência — esse é o poder da computação de borda.
Comparação das Três Principais Plataformas Edge
| Dimensão | Cloudflare Workers | Vercel Edge Functions | Deno Deploy |
|---|---|---|---|
| Runtime | V8 Isolate | V8 Isolate | Deno |
| Cold Start | <5ms | <5ms | ~20ms |
| Nós globais | 300+ cidades | 30+ regiões | 35+ regiões |
| Plano gratuito | 100K requisições/dia | Cobrança por projeto | 1M requisições/mês |
| Linguagens | JS/TS/WASM | JS/TS | JS/TS/WASM |
| Limite de tamanho do bundle | 10MB | 4MB | Ilimitado |
| Armazenamento KV | Workers KV | Edge Config | Deno KV |
| Integração com frameworks | Agnóstico a framework | Integração profunda com Next.js | Fresh |
Cenário Prático 1: Roteamento Geográfico
Direciona usuários para conteúdos diferentes com base na localização geográfica com latência zero:
// Cloudflare Workers
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const country = request.cf?.country as string;
const routes: Record<string, string> = {
CN: 'https://cn.example.com',
JP: 'https://jp.example.com',
US: 'https://us.example.com',
EU: 'https://eu.example.com',
};
const target = routes[country] || routes['US'];
return Response.redirect(target, 302);
},
};
Versão para Vercel Edge
// middleware.ts (Next.js)
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const country = request.geo?.country || 'US';
const localeMap: Record<string, string> = {
CN: '/zh-CN',
TW: '/zh-TW',
JP: '/ja',
};
const locale = localeMap[country] || '/en';
if (!request.nextUrl.pathname.startsWith(locale)) {
return NextResponse.redirect(new URL(locale, request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|_next/static).*)'],
};
Cenário Prático 2: Testes A/B
Direciona o tráfego na camada edge — sem necessidade de JavaScript no lado do cliente:
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// Read or assign experiment group
let variant = getCookie(request, 'ab-variant');
if (!variant) {
variant = Math.random() < 0.5 ? 'control' : 'experiment';
}
// Read corresponding version HTML from KV
const html = await env.KV.get(`landing:${variant}`);
const response = new Response(html, {
headers: { 'Content-Type': 'text/html' },
});
// Set cookie to maintain group consistency
response.headers.append(
'Set-Cookie',
`ab-variant=${variant}; Path=/; Max-Age=86400`
);
return response;
},
};
function getCookie(request: Request, name: string): string | null {
const cookies = request.headers.get('Cookie') || '';
const match = cookies.match(new RegExp(`${name}=([^;]+)`));
return match ? match[1] : null;
}
Comparação de Vantagens
| Abordagem | FOUC | Impacto no Desempenho | Amigável para SEO | Complexidade |
|---|---|---|---|---|
| Roteamento com JS no cliente | ❌ Piscadas | Reduz LCP | ❌ | Baixa |
| Roteamento no lado do servidor | ✅ Sem piscada | Aumenta latência | ✅ | Média |
| Roteamento Edge | ✅ Sem piscada | Quase sem impacto | ✅ | Média |
Cenário Prático 3: Conteúdo Personalizado
export default {
async fetch(request: Request, env: Env) {
const country = request.cf?.country;
const timezone = request.cf?.timezone;
// Display local time based on timezone
const localTime = new Date().toLocaleTimeString('en-US', {
timeZone: timezone,
});
// Display local currency based on country
const currencyMap: Record<string, { symbol: string; rate: number }> = {
CN: { symbol: '¥', rate: 7.2 },
JP: { symbol: '¥', rate: 150 },
US: { symbol: '$', rate: 1 },
};
const currency = currencyMap[country] || currencyMap['US'];
// Fetch base page and inject personalized data
const response = await fetch(request);
const html = await response.text();
const personalized = html
.replace('{{LOCAL_TIME}}', localTime)
.replace('{{CURRENCY_SYMBOL}}', currency.symbol);
return new Response(personalized, {
headers: response.headers,
});
},
};
Cenário Prático 4: Agregação e Cache de API
Agrega múltiplas APIs na camada edge para reduzir as requisições do cliente:
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const cache = caches.default;
const cacheKey = new Request(request.url);
// 1. Check edge cache
let response = await cache.match(cacheKey);
if (response) return response;
// 2. Parallel requests to multiple APIs
const [user, posts, notifications] = await Promise.all([
fetch('https://api.example.com/user', { headers: request.headers }),
fetch('https://api.example.com/posts?limit=10'),
fetch('https://api.example.com/notifications/unread'),
]);
// 3. Aggregate responses
const data = {
user: await user.json(),
posts: await posts.json(),
notifications: await notifications.json(),
};
response = new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=60',
},
});
// 4. Write to edge cache
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
},
};
Armazenamento KV Edge: Banco de Dados Global de Baixa Latência
Cloudflare Workers KV
// Write
await env.KV.put('user:123:preferences', JSON.stringify({
theme: 'dark',
language: 'zh-CN',
}));
// Read (eventually consistent, ~60s global sync)
const prefs = await env.KV.get('user:123:preferences', 'json');
// List
const list = await env.KV.list({ prefix: 'user:123:' });
Vercel Edge Config
import { get } from '@vercel/edge-config';
// Read configuration (globally synced, ~1s latency)
const flags = await get('feature-flags');
if (flags?.newHomepage) {
return newHomepage();
}
return oldHomepage();
Migração de Arquiteturas Tradicionais
Caminho de Migração
Fase 1: Ativos estáticos na CDN (1-2 dias)
→ HTML/JS/CSS/imagens → Cache edge da CDN
→ Requisições dinâmicas ainda vão para a origem
Fase 2: Middleware edge (1-2 semanas)
→ Redirecionamentos, testes A/B, roteamento geográfico → Edge
→ Lógica de negócio ainda na origem
Fase 3: Edge-ificação de APIs leves (2-4 semanas)
→ APIs com muita leitura → Edge + KV
→ Operações de escrita ainda vão para a origem
Fase 4: Edge-ificação de lógica pesada (sob demanda)
→ SSR → Edge SSR
→ Respostas de streaming → Edge Streaming
Considerações
| Limitação | Descrição | Mitigação |
|---|---|---|
| Sem APIs Node.js | Não há fs, path, etc. |
Usar Web APIs em vez disso |
| Limite de tempo de execução | Workers: 30ms (gratuito) / 30s (pago) | Dividir tarefas longas |
| Limite de tamanho do bundle | Workers: 10MB | Tree-shaking, WASM |
| Sem estado global | Isolate isolado por requisição | Persistir com KV/D1 |
| Cold start não zero | V8 Isolate ~5ms | Aquecer rotas principais |
Benchmarks de Desempenho
O site ToolsKu utiliza a arquitetura CDN do Cloudflare + exportação estática:
Métrica SSR Tradicional Edge Estático
TTFB 200-500ms 10-30ms
LCP 1.5-3s 0.3-0.8s
Latência Global P50 150ms 15ms
Latência Global P99 800ms 50ms
Resumo
A computação de borda é a arma definitiva para a otimização de desempenho frontend — não se trata de economizar 50ms no servidor, mas de reduzir 150ms de latência de rede para 5ms. Em 2026, se suas páginas dinâmicas ainda não rodam no edge, você está desperdiçando mais de 100ms do tempo de espera dos seus usuários. Do roteamento geográfico e testes A/B até a agregação de APIs, a computação de borda dá aos desenvolvedores frontend o superpoder de "implantar código em mais de 300 cidades ao redor do mundo".
Experimente estas ferramentas executadas localmente no navegador — nenhum cadastro necessário →