edge-rendering について
edge-renderingは、ネットワークエッジで動的ページを生成するAgent Skillsのワークフローです。テンプレート型URLを多数扱うチーム向けに、エッジでのデータ取得、ページ描画、構造化データ生成、キャッシュ管理をまとめています。
主な機能
- 01テンプレートページのオンデマンド生成
- 02都市とサービスのデータ取得
- 03JSON-LDとメタタグの動的生成
- 04stale-while-revalidateによるエッジキャッシュ
- 05サイトマップ生成のガイダンス
活用シーン
- 01都市とサービスの組み合わせページを生成
- 02グローバルなエッジキャッシュでSEOコンテンツを配信
- 03時間のかかる静的ページ構築を置き換え
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ itallstartedwithaidea/ agent-skills --skill edge-renderingインストール後、Claude Code で/edge-renderingを入力して読み込まれたか確認します。
詳細
エッジレンダリング
Agent Skills™ の一部(googleadsagent.ai™ 提供)
説明
エッジレンダリングはネットワークエッジで動的なページを生成して配信し、都市、サービス、ユーザーセグメントによって内容が異なる場合に、オリジンへの往復をなくします。このスキルは googleadsagent.ai™ のシステムを支えています。このシステムでは、116 のサービスと 155 以上の都市を組み合わせたマトリックスから 18,000 以上のページを生成し、それぞれに固有のコンテンツ、構造化データ、SEO メタデータを用意しています。これらはすべてエッジでレンダリングされ、グローバルで 50 ミリ秒未満の TTFB を実現します。
都市 × サービスのページマトリックスは、大規模なエッジレンダリングの力を示しています。18,000 の静的ページを事前に構築したり、すべてのリクエストを一元化されたオリジンにルーティングしたりする代わりに、Workers はテンプレート、KV の都市固有データ、D1 のサービスメタデータを使って、各ページをオンデマンドで生成します。レンダリングされたページは stale-while-revalidate のセマンティクスでエッジにキャッシュされ、コンテンツを新鮮に保ちながら即座に応答します。
このパターンは、SEO ランディングページだけでなく、組み合わせ可能なテンプレートに基づくあらゆるコンテンツにも適用できます。たとえば、製品 × 地域のページ、イベント × 会場のページ、サービス × 業界のページなどです。エッジレンダリングパイプラインは、テンプレートの解決、データの注入、構造化データ(JSON-LD)の生成、メタタグの構築、キャッシュ管理を統合されたシステムとして処理します。
使用する場面
- 組み合わせマトリックス(都市 × サービス、製品 × カテゴリ)からページを生成する場合
- グローバルで高速な TTFB が求められる SEO 上重要なコンテンツを配信する場合
- 数千の固有 URL を持つランディングページシステムを構築する場合
- ビルドに何時間もかかる静的サイト生成を置き換える場合
- エッジで stale-while-revalidate キャッシュを実装する場合
- ページごとに構造化データ(JSON-LD)を動的にレンダリングする場合
動作の仕組み
graph TD
A[Request: /google-ads/chicago] --> B[Worker: Parse city + service]
B --> C{Edge Cache Hit?}
C -->|Hit| D[Return Cached HTML]
C -->|Miss| E[Fetch City Data from KV]
E --> F[Fetch Service Data from D1]
F --> G[Render Template]
G --> H[Inject JSON-LD Structured Data]
H --> I[Generate Meta Tags]
I --> J[Cache at Edge]
J --> K[Return Fresh HTML]
D --> L[Background: Revalidate if Stale]
各リクエストは(都市、サービス)の組に解決されます。Worker はまずエッジキャッシュを確認します。キャッシュミスの場合、都市とサービスのデータを並列に取得し、テンプレートをレンダリングして構造化データを注入し、結果をキャッシュします。古いエントリがある場合は、応答をブロックせずにバックグラウンドで再検証します。
実装
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const [, service, city] = url.pathname.split("/");
const cacheKey = new Request(url.toString());
const cache = caches.default;
let response = await cache.match(cacheKey);
if (response) {
const age = parseInt(response.headers.get("age") ?? "0");
if (age > 3600) {
ctx.waitUntil(revalidate(env, cache, cacheKey, service, city));
}
return response;
}
return revalidate(env, cache, cacheKey, service, city);
},
} satisfies ExportedHandler<Env>;
async function revalidate(
env: Env, cache: Cache, cacheKey: Request, service: string, city: string
): Promise<Response> {
const [cityData, serviceData] = await Promise.all([
env.CITY_KV.get<CityData>(city, "json"),
env.DB.prepare("SELECT * FROM services WHERE slug = ?").bind(service).first<ServiceData>(),
]);
if (!cityData || !serviceData) {
return new Response("Not Found", { status: 404 });
}
const html = renderPage(cityData, serviceData);
const response = new Response(html, {
headers: {
"Content-Type": "text/html;charset=UTF-8",
"Cache-Control": "public, s-maxage=86400, stale-while-revalidate=3600",
},
});
await cache.put(cacheKey, response.clone());
return response;
}
function renderPage(city: CityData, service: ServiceData): string {
const jsonLd = {
"@context": "https://schema.org",
"@type": "LocalBusiness",
name: `${service.name} in ${city.name}`,
address: { "@type": "PostalAddress", addressLocality: city.name, addressRegion: city.state },
geo: { "@type": "GeoCoordinates", latitude: city.lat, longitude: city.lng },
url: `https://googleadsagent.ai/${service.slug}/${city.slug}`,
};
return `<!DOCTYPE html>
<html lang="en">
<head>
<title>${service.name} in ${city.name} | googleadsagent.ai</title>
<meta name="description" content="${service.description} for businesses in ${city.name}, ${city.state}." />
<script type="application/ld+json">${JSON.stringify(jsonLd)}</script>
</head>
<body>${service.template.replace("{{city}}", city.name)}</body>
</html>`;
}
ベストプラクティス
Promise.allを使って都市とサービスのデータを並列に取得し、順次取得は避けますstale-while-revalidateを使って、バックグラウンドで更新しながらキャッシュ済みコンテンツを配信します- 検索エンジンでの可視性を最大化するため、すべてのページで JSON-LD 構造化データを生成します
- 一貫したエッジパフォーマンスを保つため、KV の値は 25MB 未満、D1 クエリは 100ms 未満にします
- 現在の都市 × サービスのマトリックスを反映するサイトマップジェネレーターを実装します
- キャッシュヒット率を監視し、本番トラフィックでは 95%超を目標にします
プラットフォームとの互換性
| プラットフォーム | サポート | 備考 |
|---|---|---|
| Cursor | 完全 | Worker の開発とデプロイ |
| VS Code | 完全 | Wrangler との統合 |
| Windsurf | 完全 | エッジファーストの開発 |
| Claude Code | 完全 | テンプレートと Worker の生成 |
| Cline | 完全 | エッジアーキテクチャのサポート |
| aider | 部分的 | テンプレート生成のみ |
関連スキル
キーワード
edge-rendering city-service-pages cloudflare-workers seo json-ld stale-while-revalidate dynamic-pages structured-data
© 2026 googleadsagent.ai™ | Agent Skills™ | MIT License