邊緣計算×前端:Cloudflare Workers/Vercel Edge 讓你的網站快到離譜
前端工程(更新於 2026年6月2日)
為什麼前端需要邊緣計算?
傳統架構中,使用者請求需要穿越半個網際網路到達源站伺服器:
使用者(東京)→ CDN 節點(東京,僅快取靜態)→ 源站(美西,動態計算)
延遲:~10ms ~150ms 跨太平洋 ~50ms 計算
總計:~210ms
邊緣計算把計算邏輯推到離使用者最近的節點:
使用者(東京)→ Edge 節點(東京,直接計算)
延遲:~10ms ~5ms 本地計算
總計:~15ms
14 倍延遲降低——這就是邊緣計算的威力。
三大邊緣平台對比
| 維度 | Cloudflare Workers | Vercel Edge Functions | Deno Deploy |
|---|---|---|---|
| 執行環境 | V8 Isolate | V8 Isolate | Deno |
| 冷啟動 | <5ms | <5ms | ~20ms |
| 全球節點 | 300+ 城市 | 30+ 區域 | 35+ 區域 |
| 免費額度 | 10萬次/天 | 按專案計費 | 100萬次/月 |
| 語言 | JS/TS/WASM | JS/TS | JS/TS/WASM |
| 套件大小限制 | 10MB | 4MB | 無限制 |
| KV 儲存 | Workers KV | Edge Config | Deno KV |
| 框架整合 | 框架無關 | Next.js 深度整合 | Fresh |
實戰場景一:Geo 路由
根據使用者地理位置路由到不同內容,零延遲:
// 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);
},
};
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).*)'],
};
實戰場景二:A/B 測試
無需客戶端 JS,在邊緣層直接分流:
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
// 讀取或分配實驗組
let variant = getCookie(request, 'ab-variant');
if (!variant) {
variant = Math.random() < 0.5 ? 'control' : 'experiment';
}
// 從 KV 讀取對應版本的 HTML
const html = await env.KV.get(`landing:${variant}`);
const response = new Response(html, {
headers: { 'Content-Type': 'text/html' },
});
// 設定 Cookie 保持分組一致性
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;
}
優勢對比
| 方案 | 首屏閃爍 | 效能影響 | SEO 友好 | 實作複雜度 |
|---|---|---|---|---|
| 客戶端 JS 分流 | ❌ 閃爍 | 降低 LCP | ❌ | 低 |
| 伺服器端分流 | ✅ 無閃爍 | 增加延遲 | ✅ | 中 |
| 邊緣分流 | ✅ 無閃爍 | 幾乎無影響 | ✅ | 中 |
實戰場景三:個人化內容
export default {
async fetch(request: Request, env: Env) {
const country = request.cf?.country;
const timezone = request.cf?.timezone;
// 根據時區顯示本地時間
const localTime = new Date().toLocaleTimeString('zh-TW', {
timeZone: timezone,
});
// 根據國家顯示本地貨幣
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'];
// 獲取基礎頁面並注入個人化資料
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,
});
},
};
實戰場景四:API 聚合與快取
在邊緣層聚合多個 API,減少客戶端請求:
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const cache = caches.default;
const cacheKey = new Request(request.url);
// 1. 檢查邊緣快取
let response = await cache.match(cacheKey);
if (response) return response;
// 2. 並行請求多個 API
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. 聚合回應
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. 寫入邊緣快取
ctx.waitUntil(cache.put(cacheKey, response.clone()));
return response;
},
};
邊緣 KV 儲存:全球低延遲資料庫
Cloudflare Workers KV
// 寫入
await env.KV.put('user:123:preferences', JSON.stringify({
theme: 'dark',
language: 'zh-TW',
}));
// 讀取(最終一致性,~60s 全球同步)
const prefs = await env.KV.get('user:123:preferences', 'json');
// 列表
const list = await env.KV.list({ prefix: 'user:123:' });
Vercel Edge Config
import { get } from '@vercel/edge-config';
// 讀取設定(全球同步,~1s 延遲)
const flags = await get('feature-flags');
if (flags?.newHomepage) {
return newHomepage();
}
return oldHomepage();
從傳統架構遷移
遷移路徑
階段 1:靜態資源上 CDN(1-2 天)
→ HTML/JS/CSS/圖片 → CDN 邊緣快取
→ 動態請求仍走源站
階段 2:邊緣中介層(1-2 週)
→ 重定向、A/B 測試、Geo 路由 → Edge
→ 業務邏輯仍在源站
階段 3:輕量 API 邊緣化(2-4 週)
→ 讀多寫少的 API → Edge + KV
→ 寫操作仍走源站
階段 4:重度邏輯邊緣化(按需)
→ SSR → Edge SSR
→ 串流式回應 → Edge Streaming
注意事項
| 限制 | 說明 | 應對 |
|---|---|---|
| 無 Node.js API | 沒有 fs、path 等 |
使用 Web API 替代 |
| 執行時間限制 | Workers: 30ms (免費) / 30s (付費) | 拆分長任務 |
| 套件大小限制 | Workers: 10MB | Tree-shaking、WASM |
| 無全域狀態 | 每次請求獨立 Isolate | 使用 KV/D1 持久化 |
| 冷啟動雖快但非零 | V8 Isolate ~5ms | 預熱關鍵路由 |
效能實測
工具庫網站使用 Cloudflare CDN + 靜態匯出架構:
指標 傳統 SSR 邊緣靜態
TTFB 200-500ms 10-30ms
LCP 1.5-3s 0.3-0.8s
全球 P50 延遲 150ms 15ms
全球 P99 延遲 800ms 50ms
總結
邊緣計算是前端效能最佳化的終極武器——不是在伺服器上最佳化 50ms,而是把 150ms 的網路延遲降到 5ms。2026 年,如果你的動態頁面還沒有跑在邊緣上,你正在給使用者白白浪費 100ms+ 的等待時間。從 Geo 路由、A/B 測試到 API 聚合,邊緣計算讓前端開發者擁有了「在全球 300+ 城市部署程式碼」的超能力。
本站提供瀏覽器本地工具,免註冊即可試用 →
#边缘计算#CDN#Edge Functions#性能优化#Cloudflare Workers