Edge Functionsとは
Edge Functionsは、ユーザーに最も近いエッジロケーション(CDNの各拠点)でコードを実行するサーバーレス関数です。従来のサーバーレス(AWS Lambdaなど)と比較して、圧倒的に低いレイテンシーを実現します。
flowchart LR
subgraph Traditional["従来のサーバーレス"]
User1["ユーザー<br/>(東京)"] --> Region["リージョン<br/>(バージニア)"]
Region --> Response1["応答<br/>200ms"]
end
subgraph Edge["Edge Functions"]
User2["ユーザー<br/>(東京)"] --> EdgeLoc["エッジ<br/>(東京)"]
EdgeLoc --> Response2["応答<br/>20ms"]
end
主要プラットフォーム
1. Cloudflare Workers
最も成熟したエッジプラットフォームの一つです。
// Cloudflare Worker
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// キャッシュチェック
const cache = caches.default;
let response = await cache.match(request);
if (!response) {
// オリジンからフェッチ
response = await fetch(request);
// キャッシュに保存
const responseToCache = response.clone();
responseToCache.headers.set('Cache-Control', 'max-age=3600');
await cache.put(request, responseToCache);
}
return response;
},
};
2. Vercel Edge Functions
Next.jsと深く統合されたエッジ実行環境です。
// middleware.ts (Next.js)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// 地理情報に基づくルーティング
const country = request.geo?.country || 'US';
if (country === 'JP') {
return NextResponse.rewrite(new URL('/jp', request.url));
}
// A/Bテスト
const bucket = Math.random() < 0.5 ? 'a' : 'b';
const response = NextResponse.next();
response.cookies.set('ab-test', bucket);
return response;
}
export const config = {
matcher: ['/((?!api|_next/static|favicon.ico).*)'],
};
3. Deno Deploy
Deno ランタイムベースのエッジプラットフォームです。
// main.ts (Deno Deploy)
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
if (url.pathname === '/api/data') {
// KVストアからデータ取得
const kv = await Deno.openKv();
const data = await kv.get(['cache', 'data']);
if (data.value) {
return Response.json(data.value);
}
// データを生成してキャッシュ
const newData = { timestamp: Date.now(), message: 'Hello from Edge!' };
await kv.set(['cache', 'data'], newData, { expireIn: 60000 });
return Response.json(newData);
}
return new Response('Not Found', { status: 404 });
});
4. AWS Lambda@Edge / CloudFront Functions
AWSのCDNと統合されたエッジ実行環境です。
// CloudFront Function
function handler(event) {
const request = event.request;
const headers = request.headers;
// デバイス検出
const userAgent = headers['user-agent']?.value || '';
const isMobile = /Mobile|Android/i.test(userAgent);
// モバイル用URLにリダイレクト
if (isMobile && !request.uri.startsWith('/m/')) {
return {
statusCode: 302,
headers: {
location: { value: `/m${request.uri}` },
},
};
}
return request;
}
ユースケース
1. 認証・認可
// JWTトークン検証をエッジで実行
async function verifyToken(request: Request): Promise<Response | null> {
const authHeader = request.headers.get('Authorization');
if (!authHeader?.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.slice(7);
try {
const payload = await verifyJWT(token, JWT_SECRET);
// ユーザー情報をヘッダーに追加してオリジンへ転送
const newRequest = new Request(request, {
headers: new Headers(request.headers),
});
newRequest.headers.set('X-User-ID', payload.sub);
return null; // 続行
} catch {
return new Response('Invalid Token', { status: 401 });
}
}
2. パーソナライゼーション
// 地理・言語に基づくコンテンツ最適化
export default {
async fetch(request: Request): Promise<Response> {
const country = request.cf?.country || 'US';
const language = request.headers.get('Accept-Language')?.split(',')[0] || 'en';
// 地域別価格表示
const prices = {
US: { currency: 'USD', amount: 9.99 },
JP: { currency: 'JPY', amount: 980 },
EU: { currency: 'EUR', amount: 8.99 },
};
const price = prices[country] || prices['US'];
// HTMLをエッジで生成
const html = `
<!DOCTYPE html>
<html lang="${language}">
<body>
<h1>Welcome!</h1>
<p>Price: ${price.currency} ${price.amount}</p>
</body>
</html>
`;
return new Response(html, {
headers: { 'Content-Type': 'text/html' },
});
},
};
3. APIゲートウェイ
// レート制限・ルーティング
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const ip = request.headers.get('CF-Connecting-IP') || 'unknown';
// レート制限(Cloudflare Durable Objects使用)
const rateLimiter = env.RATE_LIMITER.get(env.RATE_LIMITER.idFromName(ip));
const { allowed } = await rateLimiter.fetch(request).then(r => r.json());
if (!allowed) {
return new Response('Too Many Requests', { status: 429 });
}
// パスベースルーティング
const url = new URL(request.url);
const routes = {
'/api/users': 'https://users-service.internal',
'/api/products': 'https://products-service.internal',
'/api/orders': 'https://orders-service.internal',
};
for (const [path, origin] of Object.entries(routes)) {
if (url.pathname.startsWith(path)) {
return fetch(new URL(url.pathname, origin), request);
}
}
return new Response('Not Found', { status: 404 });
},
};
4. 画像最適化
// 画像のリサイズ・フォーマット変換
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
const imageUrl = url.searchParams.get('url');
const width = parseInt(url.searchParams.get('w') || '800');
const format = url.searchParams.get('f') || 'webp';
if (!imageUrl) {
return new Response('Missing image URL', { status: 400 });
}
// Cloudflare Image Resizing
return fetch(imageUrl, {
cf: {
image: {
width,
format,
quality: 80,
},
},
});
},
};
制約と最適化
実行時間制限
| プラットフォーム | CPU時間 | 実時間 |
|---|---|---|
| Cloudflare Workers | 10ms〜50ms | 30秒 |
| Vercel Edge | 25秒 | 25秒 |
| Deno Deploy | 50ms | 無制限 |
| Lambda@Edge | 5秒 | 30秒 |
コールドスタート
// コールドスタート最小化のベストプラクティス
// 1. グローバルスコープで初期化を避ける
// Bad
const heavyConfig = loadHeavyConfig(); // 毎回実行される
// Good
let cachedConfig: Config | null = null;
function getConfig(): Config {
if (!cachedConfig) {
cachedConfig = loadConfig();
}
return cachedConfig;
}
メモリ制限
// ストリーミング処理でメモリを節約
export default {
async fetch(request: Request): Promise<Response> {
const response = await fetch('https://api.example.com/large-data');
// ストリーム変換
const transformStream = new TransformStream({
transform(chunk, controller) {
// チャンクごとに処理
const processed = processChunk(chunk);
controller.enqueue(processed);
},
});
return new Response(response.body?.pipeThrough(transformStream), {
headers: response.headers,
});
},
};
プラットフォーム比較
| 特徴 | Cloudflare Workers | Vercel Edge | Deno Deploy |
|---|---|---|---|
| ランタイム | V8 Isolates | V8 Isolates | Deno |
| グローバル拠点 | 300+ | 100+ | 35+ |
| KVストア | ◎ Workers KV | ○ Edge Config | ◎ Deno KV |
| データベース | ◎ D1 (SQLite) | ○ Postgres | ○ KV |
| 無料枠 | 100k req/日 | 100k req/月 | 100k req/日 |
関連記事
まとめ
Edge Functionsは、グローバルに低レイテンシーなアプリケーションを構築するための強力なツールです。
- 低レイテンシー: ユーザーに最も近い場所で実行
- グローバル配信: 自動的に世界中に展開
- コスト効率: 使用量ベースの課金
- シンプルなデプロイ: git pushで即座に反映
認証、パーソナライゼーション、APIゲートウェイなど、適切なユースケースを選んで活用しましょう。
← 一覧に戻る