Workers KVを使用して静的アセットを保存および取得する
Workers KVを使用して静的アセットを保存および取得する
静的アセットをWorkers KVに保存することで、これらのアセットを低遅延かつ高スループットでグローバルに取得できます。これらのアセットを直接提供することも、動的に応答を生成するために使用することもできます。これは、ファイルや画像を提供する場合や、翻訳などの静的アセットから動的なHTML応答を生成する場合に便利です。
All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3 ↗, and Wrangler.
始めるには、create-cloudflare CLI ↗を使用してWorkerアプリケーションを作成します。ターミナルウィンドウを開き、次のコマンドを実行します。
npm create cloudflare@latest -- example-kv-assetsyarn create cloudflare@latest example-kv-assetspnpm create cloudflare@latest example-kv-assetsFor setup, select the following options:
- For What would you like to start with?, choose
Hello Worldの例. - For Which template would you like to use?, choose
Hello World Worker. - For Which language do you want to use?, choose
TypeScript. - For Do you want to use git for version control?, choose
Yes. - For Do you want to deploy your application?, choose
No(we will be making some changes before deploying).
次に、新しく作成したアプリケーションに移動します。
cd example-kv-assetsこのプロジェクトに必要な依存関係もインストールします。
npm install mimes accept-language-parsernpm install --save-dev @types/accept-language-parser次に、KVストアを作成します。これはCloudflareダッシュボードまたはWrangler CLIを通じて行うことができます。この例では、Wrangler CLIを使用します。
Wranglerを介してKVストアを作成するには:
-
ターミナルを開き、次のコマンドを実行します:
Terminal window npx wrangler kv namespace create assetswrangler kv namespace create assetsサブコマンドは、Workerの名前とassetsに提供された値を連結してKV名前空間を作成します。KV名前空間のidはランダムに生成されます。Terminal window npx wrangler kv namespace create assets🌀 "example-kv-assets-assets"というタイトルの名前空間を作成中✨ 成功!kv_namespaces配列の設定ファイルに次の内容を追加してください:[[kv_namespaces]]binding = "assets"id = "<GENERATED_NAMESPACE_ID>" -
wrangler.tomlファイルに、ターミナルで生成された値を使用して次の内容を追加します:wrangler.toml [[kv_namespaces]]binding = "assets"id = "<GENERATED_NAMESPACE_ID>"KVバインディング
assetsは、WorkerがKV名前空間と対話する方法です。このバインディングは、WorkersランタイムによってWorkersコード内のランタイム変数として提供されます。プレビューKV名前空間も作成します。ローカルで開発する際に本番名前空間に変更を加えないように、別のKV名前空間を作成することをお勧めします。リモートリソースに対してローカルで開発する場合、Wrangler CLIは
wrangler.tomlファイルのKV名前空間設定内のpreview_idで指定された名前空間のみを使用します。 -
ターミナルで次のコマンドを実行します:
Terminal window npx wrangler kv namespace create assets --previewこのコマンドは、リモートリソースに対してWranglerで開発する際にのみ使用される特別なKV名前空間を作成します。
Terminal window npx wrangler kv namespace create assets --preview🌀 "example-kv-assets-assets_preview"というタイトルの名前空間を作成中✨ 成功!kv_namespaces配列の設定ファイルに次の内容を追加してください:[[kv_namespaces]]binding = "assets"preview_id = "<GENERATED_PREVIEW_NAMESPACE_ID>" -
wrangler.tomlファイルに、ターミナルで生成された値を使用してkv_namespacesの下に追加のpreview_idを追加します:wrangler.toml [[kv_namespaces]]binding = "assets"id = "<GENERATED_NAMESPACE_ID>"preview_id = "<GENERATED_PREVIEW_NAMESPACE_ID>"
これで、デプロイ時に本番KV名前空間を使用し、リモートリソースに対してローカルで開発する際にプレビューKV名前空間を使用する1つのKVバインディングができました。
静的アセットをKVに保存するには、Wrangler CLI、WorkerアプリケーションからのKVバインディング、またはKV REST APIを使用できます。ここでは、Wrangler CLIの使用方法を示します。
このシナリオでは、サンプルHTMLファイルをKVストアに保存します。プロジェクトのルートにindex.htmlという新しいファイルを作成し、次の内容を追加します:
Hello World!次に、次のWranglerコマンドを使用して、このファイルのKVペアを本番およびプレビュー名前空間内に作成できます:
npx wrangler kv key put index.html --path index.html --binding assets --preview falsenpx wrangler kv key put index.html --path index.html --binding assets --previewこれにより、ファイル名をキー、ファイル内容を値とするKVペアが、wrangler.tomlファイル内のバインディングで指定された本番およびプレビュー名前空間内に作成されます。
Workerプロジェクトのindex.tsファイル内の内容を次のように置き換えます:
import mime from 'mime';
interface Env { assets: KVNamespace;}
export default { async fetch(request, env, ctx): Promise<Response> { // GETリクエストでない場合はエラーを返す if(request.method !== 'GET'){ return new Response('Method Not Allowed', { status: 405, }) }
// URLからキーを取得し、キーが欠けている場合はエラーを返す const parsedUrl = new URL(request.url) const key = parsedUrl.pathname.replace(/^\/+/, '') // 前の/を削除 if(!key){ return new Response('Missing path in URL', { status: 400 }) }
// キーパスからMIMEタイプを取得 const extension = key.split('.').pop(); let mimeType = mime.getType(key) || "text/plain"; if (mimeType.startsWith("text") || mimeType === "application/javascript") { mimeType += "; charset=utf-8"; }
// KVストアから値を取得し、見つかった場合は返す const value = await env.assets.get(key, 'arrayBuffer') if(!value){ return new Response("Not found", { status: 404 }) } return new Response(value, { status: 200, headers: new Headers({ "Content-Type": mimeType }) }); },} satisfies ExportedHandler<Env>;このコードは、URL内のパスを使用してKVストア内のパスに関連付けられたファイルを見つけます。また、応答内で適切なMIMEタイプを設定して、ブラウザに応答の処理方法を示します。KVストアから値を取得するために、このコードはarrayBufferを使用して、画像、文書、ビデオ/オーディオファイルなどのバイナリデータを適切に処理します。
Workerを開始するには、ターミナル内で次のコマンドを実行します:
npx wrangler dev --remoteこれにより、リモートリソースに対してWorkerコードが実行され、特に構成されたプレビューKV名前空間が使用されます。
npx wrangler dev --remoteあなたのWorkerは次のバインディングにアクセスできます:- KV名前空間: - assets: <GENERATED_PREVIEW_NAMESPACE_ID>[wrangler:inf] http://localhost:<PORT>で準備完了Wranglerコマンドによって提供されたURLにアクセスすると、index.htmlファイルの内容が含まれたHTMLファイルが返されるのが確認できます。画像や文書で試してみると、このWorkerがKVからそれらのアセットを適切に提供していることがわかります。
KVに保存されたアセットから動的応答を生成する方法を示すために、Workersアプリケーションにhello-worldエンドポイントを追加します。このエンドポイントは、要求された言語に基づいて「Hello World!」メッセージを返します。
プロジェクトのルートに次のファイルを作成します:
[ { "language_code": "en", "message": "Hello World!" }, { "language_code": "es", "message": "¡Hola Mundo!" }, { "language_code": "fr", "message": "Bonjour le monde!" }, { "language_code": "de", "message": "Hallo Welt!" }, { "language_code": "zh", "message": "你好,世界!" }, { "language_code": "ja", "message": "こんにちは、世界!" }, { "language_code": "hi", "message": "नमस्ते दुनिया!" }, { "language_code": "ar", "message": "مرحبا بالعالم!" }]ターミナルを開き、次のKVコマンドを入力して翻訳ファイルのKVエントリを作成します:
npx wrangler kv key put hello-world.json --path hello-world.json --binding assets --preview falsenpx wrangler kv key put hello-world.json --path hello-world.json --binding assets --previewWorkersコードを更新して、リクエストのAccept-Languageヘッダーの言語に基づいて翻訳されたHTMLファイルを提供するロジックを追加します:
import mime from 'mime';import parser from 'accept-language-parser'
interface Env { assets: KVNamespace;}
export default { async fetch(request, env, ctx): Promise<Response> { // GETリクエストでない場合はエラーを返す if(request.method !== 'GET'){ return new Response('Method Not Allowed', { status: 405, }) }
// URLからキーを取得し、キーが欠けている場合はエラーを返す const parsedUrl = new URL(request.url) const key = parsedUrl.pathname.replace(/^\/+/, '') // 前の/を削除 if(!key){ return new Response('Missing path in URL', { status: 400 }) }
// 翻訳パスのハンドラーを追加 if(key === 'hello-world'){ // リクエストから言語ヘッダーを取得し、KVから翻訳を取得 const languageHeader = request.headers.get('Accept-Language') || 'en'//デフォルトは英語 const translations : { "language_code": string, "message": string }[] = await env.assets.get('hello-world.json', 'json') || [];
// 要求された言語を抽出 const supportedLanguageCodes = translations.map(item => item.language_code) const languageCode = parser.pick(supportedLanguageCodes, languageHeader, { loose: true })
// 選択された言語のメッセージを取得 let selectedTranslation = translations.find(item => item.language_code === languageCode) if(!selectedTranslation) selectedTranslation = translations.find(item => item.language_code === "en") const helloWorldTranslated = selectedTranslation!['message'];
// 翻訳されたHTMLを生成して返す const html = `<!DOCTYPE html> <html> <head> <title>Hello World翻訳</title> </head> <body> <h1>${helloWorldTranslated}</h1> </body> </html> ` return new Response(html, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' } }) }
// キーパスからMIMEタイプを取得 const extension = key.split('.').pop(); let mimeType = mime.getType(key) || "text/plain"; if (mimeType.startsWith("text") || mimeType === "application/javascript") { mimeType += "; charset=utf-8"; }
// KVストアから値を取得し、見つかった場合は返す const value = await env.assets.get(key, 'arrayBuffer') if(!value){ return new Response("Not found", { status: 404 }) } return new Response(value, { status: 200, headers: new Headers({ "Content-Type": mimeType }) }); },} satisfies ExportedHandler<Env>;この新しいコードは、特定のエンドポイント/hello-worldを提供し、翻訳された応答を提供します。このURLにアクセスすると、Workerコードは最初にクライアントがAccept-Languageリクエストヘッダーで要求した言語とKVストアからの翻訳を取得します。次に、翻訳されたメッセージを取得し、生成されたHTMLを返します。
npx wrangler dev --remoteWorkerコードが実行されている状態で、アプリケーションが適切に翻訳された「Hello World」メッセージを返していることがわかります。ブラウザの開発者コンソールからロケール言語を変更してみてください(Chromiumブラウザでは、Show Sensorsを実行してロケールの選択ドロップダウンを取得できます)。
wrangler deployを実行して、WorkersプロジェクトをCloudflareにデプロイし、KV名前空間へのバインディングを設定します。
npx wrangler deployWranglerは自動的にKVバインディングを設定し、wrangler.tomlファイルに設定されたKV名前空間IDを使用して本番KV名前空間を使用します。この例では、アセットをプレビューおよび本番KV名前空間の両方にアップロードしました。
プロジェクトが正しく動作していることを確認するために、Workersのデフォルトホスト名にアクセスし、<WORKER-SUBDOMAIN>.<DEFAULT-ACCOUNT-HOSTNAME>.dev/index.htmlまたは<WORKER-SUBDOMAIN>.<DEFAULT-ACCOUNT-HOSTNAME>.dev/hello-worldにアクセスして、KVストアの値から応答を生成するデプロイされたWorkerを確認できます。