Edge Website Building

最終更新日:2024-09-03 17:00:38

この例では、Edge KVEdge Cloud Apps関数を使用して、小さな静的Webサイトを構築する方法を示します。関数は、URLパスに基づいてEdge KVからファイルを取得し、適切なコンテンツタイプを決定し、コンテンツをクライアントに返送します。このアプローチは、高性能、高可用性、低レイテンシーで軽量な静的Webサイトを迅速にデプロイするのに最適です。

エッジ静的Webサイトの利点

  • **サーバーレスアーキテクチャ:**従来のWebサーバーが不要になるため、運用コストが削減されます。
  • **分散デプロイメント:**Webサイトのリソースは、分散されたEdge KVに保存され、Webサイトの可用性と耐障害性が向上します。
  • **インスタントアップデート:**Webサイトのコンテンツの更新は、すべてのエッジノードにすばやく同期され、迅速なデプロイメントが可能になります。
  • **ユーザーへの近接性:**ユーザーは、最も近いエッジノードからWebサイトのコンテンツにアクセスできるため、レイテンシーが最小限に抑えられ、ユーザーエクスペリエンスが向上します。

この例では、Edge KVは、HTMLファイル、画像、ビデオなどのWebサイトの静的リソースを保存する役割を果たします。Edge Cloud Apps関数は、ユーザーリクエストを処理し、リクエストされたURLに基づいてEdge KVから対応するリソースを取得し、ユーザーに返します。

コード例

/* 
 * Edge KVのデータ保存形式:
 * | キー            | 値        |
 * | -------------- | ------------ |
 * | /index.html    | 対応するファイルデータ |
 * | /img/about.jpg | 対応するファイルデータ |
 * リクエストされたURLがhttp://www.test.com/catalog-z/index.htmlであると想定します
 * 最後のファイル名/index.htmlをキーとして使用して、ファイルデータを取得します。
 */
async function handleRequest(request) {
    // URLからリクエストされたファイル名を取得します
    let { pathname } = new URL(request.url.toLowerCase());
    if (pathname.endsWith('/')) { 
        pathname = pathname.substring(0, pathname.length - 1); 
    }
    pathname = pathname.substring("/catalog-z".length); // パスプレフィックスを削除します
    if (pathname === '') { 
        pathname = '/index.html'; // デフォルトはindex.htmlです
    }

    // ファイル名をキーとして使用して、Edge KVからファイルコンテンツを取得します。
    // ネームスペースは、ファイルのアップロード時に使用された「catalog_z2」であることに注意してください。
    const kv = new EdgeKV({namespace: "catalog_z2"});
    const content = await kv.get(pathname, {type: "stream"});

    // ファイルが見つからない場合は、404エラーを返します
    if (content === null) {
        return new Response("ページが見つかりません", {status: 404}); 
    }

    // クライアントへのレスポンスを生成します
    const contentType = contentTypeOfFile(pathname); // ファイル名に基づいてコンテンツタイプを決定します
    const headers = { 'Content-Type': contentType, 'Cache-Control': 'max-age=180' }; // キャッシュコントロールを設定します
    console.log(`リクエストされたファイル名: ${pathname}、タイプ: ${contentType}`); 
    return new Response(content, {headers: headers}); 
}

// ファイル拡張子に基づいてContent-Typeを決定します
function contentTypeOfFile(fileName) {
    const ext = fileName.split('.').pop();
    switch (ext) {
        case 'html':    return 'text/html';
        case 'css':     return 'text/css';
        case 'js':      return 'application/javascript';
        case 'jpg':     return 'image/jpeg';
        case 'png':     return 'image/png';
        case 'mp4':     return 'video/mp4';
        case 'eot':     return 'application/vnd.ms-fontobject';
        case 'svg':
        case 'svgz':    return 'image/svg+xml';
        case 'woff':    return 'font/woff';
        case 'woff2':   return 'font/woff2';
        default:        return 'application/octet-stream';
    }
}
                    
addEventListener("fetch", event => {
    return event.respondWith(handleRequest(event.request));
});