Workers KV に静的アセットを保存すると、これらのアセットをグローバルに、低レイテンシかつ高スループットで取得できます。アセットをそのまま配信することも、動的なレスポンスの生成に使うこともできます。カスタムスクリプト、KV の制限 に収まる小さな画像の配信や、翻訳などの静的アセットから動的な HTML レスポンスを生成するときに役立ちます。
静的アセットを Workers KV に保存するには、Wrangler CLI(開発時によく使います)、Workers アプリケーションからの Workers KV バインディング、または Workers KV REST API(外部アプリケーションから Workers KV にアクセスするときに使います)を使えます。ここでは Wrangler CLI の使い方を示します。
このシナリオでは、サンプルの HTML ファイルを Workers KV ストアに保存します。
次の内容で新しいファイル index.html を作成します。
Hello World!次の Wrangler コマンドで、本番およびプレビューの名前空間に、このファイルの KV ペアを作成できます。
npx wrangler kv key put index.html --path index.html --namespace-id=<ENTER_NAMESPACE_ID_HERE>これにより、ファイル名をキー、ファイル内容を値とする KV ペアが、Wrangler ファイルのバインディングで指定した本番およびプレビューの名前空間に作成されます。
この例では、Workers アプリケーションは HTTP リクエストのパスを任意のキー名として受け取り、そのキーに対応する KV ストアの値を返します。
import mime from "mime";
interface Env {
assets: KVNamespace;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
// Return error if not a get request
if(request.method !== 'GET'){
return new Response('Method Not Allowed', {
status: 405,
})
}
// Get the key from the url & return error if key missing
const parsedUrl = new URL(request.url)
const key = parsedUrl.pathname.replace(/^\/+/, '') // Strip any preceding /'s
if(!key){
return new Response('Missing path in URL', {
status: 400
})
}
// Get the mimetype from the key path
const extension = key.split('.').pop();
let mimeType = mime.getType(extension) || "text/plain";
if (mimeType.startsWith("text") || mimeType === "application/javascript") {
mimeType += "; charset=utf-8";
}
// Get the value from the Workers KV store and return it if found
const value = await env.assets.get(key, 'arrayBuffer')
if(!value){
return new Response("Not found", {
status: 404
})
}
// Return the response from the Workers application with the value from the KV store
return new Response(value, {
status: 200,
headers: new Headers({
"Content-Type": mimeType
})
});
},
} satisfies ExportedHandler<Env>;{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "2025-03-03",
"observability": {
"enabled": true
},
"kv_namespaces": [
{
"binding": "assets",
"id": "<YOUR_BINDING_ID>"
}
]
}このコードは、HTTP リクエストから取得するキーと値のペアのキー名を解析します。次に、ブラウザーがレスポンスをどう扱うかを知らせるため、適切な MIME タイプを判定します。
KV ストアから値を取得するとき、このコードは arrayBuffer を使い、画像、ドキュメント、動画 / 音声ファイルなどのバイナリデータを正しく扱います。
Workers KV 名前空間に、キー index.html と HTML コンテンツを値とするサンプルのキーと値のペアがある場合、Workers アプリケーションの https://<YOUR-WORKER-HOSTNAME>/index.html にアクセスすると、index.html ファイルの内容を確認できます。
画像やドキュメントでも試すと、この Worker が KV からそれらのアセットも正しく配信することがわかります。
静的アセットの配信に加え、KV ストアに保存した値をもとに、動的な HTML や API レスポンスを生成することもできます。
- まず、プロジェクトのルートに次のファイルを作成します。
[
{
"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 --namespace-id=<ENTER_NAMESPACE_ID_HERE>- Workers のコードを更新し、リクエストの 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> {
// Return error if not a get request
if(request.method !== 'GET'){
return new Response('Method Not Allowed', {
status: 405,
})
}
// Get the key from the url & return error if key missing
const parsedUrl = new URL(request.url)
const key = parsedUrl.pathname.replace(/^\/+/, '') // Strip any preceding /'s
if(!key){
return new Response('Missing path in URL', {
status: 400
})
}
// Add handler for translation path (with early return)
if(key === 'hello-world'){
// Retrieve the language header from the request and the translations from Workers KV
const languageHeader = request.headers.get('Accept-Language') || 'en' // Default to English
const translations : {
"language_code": string,
"message": string
}[] = await env.assets.get('hello-world.json', 'json') || [];
// Extract the requested language
const supportedLanguageCodes = translations.map(item => item.language_code)
const languageCode = parser.pick(supportedLanguageCodes, languageHeader, {
loose: true
})
// Get the message for the selected language
let selectedTranslation = translations.find(item => item.language_code === languageCode)
if(!selectedTranslation) selectedTranslation = translations.find(item => item.language_code === "en")
const helloWorldTranslated = selectedTranslation!['message'];
// Generate and return the translated html
const html = `<!DOCTYPE html>
<html>
<head>
<title>Hello World translation</title>
</head>
<body>
<h1>${helloWorldTranslated}</h1>
</body>
</html>
`
return new Response(html, {
status: 200,
headers: {
'Content-Type': 'text/html; charset=utf-8'
}
})
}
// Get the mimetype from the key path
const extension = key.split('.').pop();
let mimeType = mime.getType(extension) || "text/plain";
if (mimeType.startsWith("text") || mimeType === "application/javascript") {
mimeType += "; charset=utf-8";
}
// Get the value from the Workers KV store and return it if found
const value = await env.assets.get(key, 'arrayBuffer')
if(!value){
return new Response("Not found", {
status: 404
})
}
// Return the response from the Workers application with the value from the KV store
return new Response(value, {
status: 200,
headers: new Headers({
"Content-Type": mimeType
})
});
},
} satisfies ExportedHandler<Env>;{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "2025-03-03",
"observability": {
"enabled": true
},
"kv_namespaces": [
{
"binding": "assets",
"id": "<YOUR_BINDING_ID>"
}
]
}この新しいコードは、翻訳済みレスポンスを返す専用エンドポイント /hello-world を提供します。この URL にアクセスすると、Worker のコードはまず、クライアントが Accept-Language リクエストヘッダーで要求した言語と、hello-world.json キーの翻訳を KV ストアから取得します。次に、翻訳済みメッセージを取得し、生成した HTML を返します。
Worker アプリケーションの https://<YOUR-WORKER-HOSTNAME>/hello-world にアクセスすると、適切に翻訳された "Hello World" メッセージが返ることがわかります。
ブラウザーの開発者コンソールで、ロケール言語を変更します(Chromium 系ブラウザーでは、Show Sensors を実行するとロケールのドロップダウンが表示されます)。Worker がロケール言語に応じた翻訳メッセージを返すことが確認できます。