Cloudflare WorkersではServerlessな実行環境でJavaScriptのコードを実行することができます。SeverlessということでJavaScriptを実行するサーバなどのインフラの準備、メンテナンスはCloudflareが行うので開発者はコードの作成のみに集中することができます。コードの作成後にデプロイした(Cloudflareにコードをアップロード)コードはある特定の場所にあるデータセンターのサーバに保存されるのではなく世界中に分散するCDNのエッジにデプロイされるため世界中のどこからアクセスしても高速に応答することができます。

本文書では初めてCloudflare Workersを使う人を対象にアカウントの作成からデプロイの方法、シンプルなコードを使ってCloudflareの基本的な利用方法の説明を行なっています。Servelessな環境を利用した経験がない人であればCloudflare Workersでは自分で実行環境を構築することもなく作成したコードを簡単にインターネット上に公開することができるのでCloudflare Workersの動作確認を行いながらServerlessとは何かも理解できるかと思います。

動作確認はmacOSで行なっています。

Cloudflare Workersアカウントの作成

Cloudflare Workersを利用するためにはアカウントの作成が必要となります。アカウントを作成するためにhttps://workers.cloudflare.com/にアクセスを行い、画面中央にある”Start building”ボタンをクリックするか画面右上にある”Sign up”ボタンをクリックします。

Cloudflare Workersトップページ
Cloudflare Workersトップページ

サインアップ画面が表示されるのでEmailアドレスとパスワードを入力します。画面は英語となっていますが言語を変更したい場合には右上にあるEnglish(US)をクリックするとドロップダウンメニューで日本語を選択することができます。

サインアップ画面
サインアップ画面

EmailとPasswordを入力後”Create Account”ボタンをクリックします。クリックするとサブドメインを設定する画面が表示されます。サブドメインには任意の名前を入力してください。例えば”my-worker”というWorkerを作成した場合にWorkderを実行するためにアクセスするURLはhttps://my-workder.サブドメイン名.workers.devとなります。入力したら”Set up”ボタンをクリックしてください。

サブドメインの設定
サブドメインの設定

プランの選択画面が表示されます。”Free”と”Paid”プランを2つを選択することができます。1リクエストに対して10msのCPU timeや1日に100,000リクエストという制限がありますが動作確認するためには十分すぎるのでFreeプランを選択します。

Freeプランの選択
Freeプランの選択

プランを選択するとアカウント登録時に入力したEmailにメールが送信されるので確認します。

メールの送信画面
メールの送信画面

Cloudlareからメールが届いているか確認を行います。

Cloudflareから送信されるメールの確認
Cloudflareから送信されるメールの確認

メールのリンクをCloudflareへのリダイレクトが行われクリックすると認証が完了します。

認証の完了
認証の完了

Cloudflare WorkersのCLIのインストール

Cloudflare Workersを作成するために利用するコマンドラインツールwranglerのインストールを行います。プロジェクトの作成や作成したWorkerのデプロイに利用します。

インストールを行うためにはnpmまたはyarnコマンドが必要となります。インストールが行われていない場合はどちらかのインストールを行ってください。


 % npm install -g wrangler
or
 % yarn global add wrangler

インストールが完了したらオプションの–versionを利用してバージョンの確認を行います。本文書では2.0.8がインストールされたことがわかります。


 % wrangler --version
2.0.8

インストールが完了するとCloudflareのリソースにアクセスするために認証を行う必要があります。認証を行うことで作成したWorkerをCloudflareにデプロイするといったことがコマンドラインで行えるようになります。


 % wrangler login
 ⛅️ wrangler 2.0.8 
-------------------
Attempting to login via OAuth...

wrangler loginを実行すると自動でブラウザのタブが開き、wranglerコマンドからのアクセスを許可するか聞かれるので”Allow”を選択します。

アクセスの許可
アクセスの許可

設定が完了すると以下の画面が表示されます。

許可の完了画面
許可の完了画面

実行したコンソールには”Successfull logged in.”が表示されます。


 % wrangler login
 ⛅️ wrangler 2.0.8 
-------------------
Attempting to login via OAuth...
Successfully logged in.

プロジェクトの作成

新規のプロジェクトを作成したい場合はwrangler initコマンドを実行します。initの後ろには任意のプロジェクト名をつけることができます。ここではmy-workerという名前をつけています。

コマンドを実行するとgitを利用するか、package.jsonを作成するか、typescriptを利用するか、作成するWorkerのテンプレートについて4つの質問があります。ここではTypeScriptを利用しないのでnを選択してWorkerでは”Fetch handler”を選択しています。Workerの選択によってテンプレートファイルの内容が変わります。


 % wrangler init my-worker
 ⛅️ wrangler 2.0.8 
-------------------
Using npm as package manager.
✨ Created my-worker/wrangler.toml
Would you like to use git to manage this Worker? (y/n)
No package.json found. Would you like to create one? (y/n)
✨ Created my-worker/package.json
Would you like to use TypeScript? (y/n)
Would you like to create a Worker at my-worker/src/index.js?
  None
❯ Fetch handler
  Scheduled handler
✨ Created my-worker/src/index.js
npm WARN deprecated rollup-plugin-inject@3.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.

added 57 packages, and audited 58 packages in 8s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

To start developing your Worker, run `cd my-worker && npm start`
To publish your Worker to the Internet, run `npm run deploy`
wranger initコマンドを実行すると警告メッセージが表示されます。▲ [WARNING] The `init` command is no longer supported. Please use `npm create cloudflare\@2 — my-worker` instead.今後はnpm create cloudflareコマンドを利用します。

wrangler initコマンドでスクラッチからWorkerのコードを作成するのではなく、JavaScript/TypeScript以外の言語を利用する場合やGraphQL Serverを利用したい場合のリポジトリがQuickStartページに準備されています。

プロジェクトの作成が完了したらプロジェクト名で指定した名前のフォルダが作成されるので移動します。


 % cd my-worker

my-workerフォルダにはnode_modules、srcフォルダの他package.json, package-lock.jsonとwrangler.tomlファイルが作成されます。srcフォルダの中にはWorkerの実行ファイルであるindex.jsファイルが作成されています。

フォルダ構成
フォルダ構成

index.jsではリクエストを受け取るとfetch関数が実行されResponseクラスの引数に設定した”Hello World!”が戻されるといったシンプルなコードです。


export default {
  async fetch(request) {
    return new Response("Hello World!");
  },
};

動作確認

動作確認を行うためにnpm startコマンドを実行します。npm startコマンドを実行するとローカル環境で作成したコードの動作確認を行うことができます。キーボードの”b”, “d”, “l”, “c”, “x”キーを利用することでキーに割り当てられた操作を行うことができます。


 % npm start

> my-worker@0.0.0 start
> wrangler dev

 ⛅️ wrangler 2.0.8 
-------------------
⬣ Listening at http://localhost:8787
Script modified; context reset.
10:43:13 GET / 200
10:43:14 GET /favicon.ico 200
╭──────────────────────────────────────────────────────────────────────────────╮
│ [b open a       [d open        [l] turn on local   [c clear console[x to     │
│   browser,        Devtools,       mode,                              exit    │
╰──────────────────────────────────────────────────────────────────────────────

“b”を押すとブラウザが起動して”Hello World”が表示されます。ローカル用で利用するポートは8787です。このURLにアクセスするとsrcフォルダのindex.jsの処理が実行されます。

ブラウザからの動作確認
ブラウザからの動作確認

デプロイの方法

ローカルでの動作確認を行うことができたのでデプロイしたい場合はnpm run deployコマンドで実行することができます。コマンドを実行するだけでデプロイを行うための特別な設定を行う必要はありません。コマンドのメッセージにはUploadedとPublished、それとデプロイしたコードを実行するURLが表示されます。


% npm run deploy

> my-worker@0.0.0 deploy
> wrangler publish

 ⛅️ wrangler 2.0.8 
-------------------
Uploaded my-worker (1.32 sec)
Published my-worker (3.92 sec)
  my-worker.reffect.workers.dev

URLにアクセスする前にCloudFlareの管理画面にアクセスしてWorkersのOverviewのメニューを確認するとデプロイしたmy-workerを確認することができます。

デプロイしたコードの確認
デプロイしたコードの確認

管理画面上からもデプロイしたWorkerを確認することができたのでブラウザからはmy-worker.reffect.workers.devからアクセスを行います。

デプロイしたWorkerの実行
デプロイしたWorkerの実行

ここまでの処理でインターネット上にWorkerを公開することができるようになりました。ここまでの流れの中でサーバなどインフラに関係する処理は一切行っていません。しかしコードを実行するための環境はすべてCloudflare側で用意されているためデプロイするだけでコードを実行することができました。Cloudflare側ではサーバが常時起動しているわけではなく指定したURLにリクエストがあると作成したWorkerのコードが実行されます。

このようにServerless環境ではコードを動作させるインフラを気にすることなく実行するコードの作成のみに集中することができます。

Responseの設定

最初の例ではRequestを送ってきた相手に戻すResponseでは”Hello World”の文字列のみを戻していました。そのためブラウザでソースを見るとタグのないただの文字列が表示されることが確認できます。

Responseでは文字列だけではなくHTMLやJSONデータを戻すことができヘッダーでContent-Typeを指定することもできます。

Reponseの第一引数にはbody, 第二引数にはoptionsを設定することができます。optionsの中でヘッダーを設定することができます。


let response = new Response(body, options);

JSONデータを戻す

userオブジェクトを定義してJSON.stringifyで文字列に変換しヘッダーのcontent-typeにapplication/jsonを設定することでJSONデータを戻すことができます。ここでは定義したuserオブジェクトをJSONで戻すだけですがWorkerからfetch関数を利用して他のサービスにアクセスしてデータを取得してJSONとして戻すということも可能です。後ほど動作確認します。


export default {
  async fetch(request) {
    const user = {
      name: 'John',
    };
    return new Response(JSON.stringify(user), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};

npm startコマンドを実行してローカル環境で動作確認を行うとhttp://localhost:8787/にアクセスすると定義したuserの内容がJSONで戻されます。

importを利用

index.jsファイル内で定義したuserを別ファイルからimportして利用することも可能です。srcフォルダにdata.jsonファイルを作成します。


{ "name": "John" }

index.jsファイルではimportを利用してdata.jsonの中のデータを取り出してJSONデータとしてResponseで戻すことができます。


import user from './data.json';

export default {
  async fetch(request) {
    return new Response(JSON.stringify(user), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};

このようにWorkerはindex.jsファイルのみだけではなくimportを利用して複数のファイルでアプリケーションを構成することができます。

HTMLを戻す

JSONデータを戻すことが大半だと思いますがHTML文を戻す方法も確認しておきます。htmlの中にhtml文を保存してResponseの引数に定義したhtmlを指定します。


const html = `
<html>
<body>
<h1>Hello World</h1>
</body>
</html
`;

export default {
  async fetch(request) {
    return new Response(html);
  },
};

http://localhost:8787/にアクセスするとブラウザ上ではHTMLと認識されず文字列として表示されます。

HTMLタグを文字列として認識
HTMLタグを文字列として認識

HTMLとして表示させるためにはheadersのcontent-typeを変更する必要があります。デフォルトではtext/plainになっているためcontent-typeをtext/htmlに変更します。


//略

export default {
  async fetch(request) {
    return new Response(html, {
      headers: {
        'content-type': 'text/html',
      },
    });
  },
};

変更するとブラウザ側でHTMLとして認識しh1タグとしてHello Worldが表示されます。

HTMLとして認識
HTMLとして認識

Requestについて

Responseについて確認を行なったので次はRequestについて確認を行います。Requestのプロパティにはbody, headers, methodなどがありますがそのほかに Cloudflareのエッジネットワークによって提供されるcfというプロパティがあります。cfはIncomingRequestCfPropertiesというオブジェクトでアクセスが来た国や都市などの情報も含まれています。どのような情報が含まれているか下記のコードを利用することが確認することができます。詳細についてはドキュメントから確認できます。


export default {
  async fetch(request) {
    return new Response(JSON.stringify(request.cf, null, 2), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};
JSON.stringifyではブラウザ上に表示されるJSONデータを整形するためにオプションを設定しています。

設定後ブラウザ上からアクセスを行い確認すると国や都市以外にもさまざまな情報が含まれていることがわかります。

request.cfオブジェクトに含まれるプロパティ
request.cfオブジェクトに含まれるプロパティ

countryには”JP”が入っています。スクロールするとregion, city, timezoneが確認できます。東京であればregionにtokyoでcityには区の情報が含まれます。

JSONデータの取得

JSONデータを含むPOSTリクエストが送信されてきた場合に含まれるrequest.json()を利用するでJSONデータを取得することができます。request.json()はpromiseを戻すのでawaitを設定する必要があります。ここでは受け取ったデータはそのままJSON.stringifyを利用して戻します。


export default {
  async fetch(request) {
    const body = await request.json();
    return new Response(JSON.stringify(body), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};

JSONデータのPOSTリクエストにVSCodeのExtensionのREST Clientを利用します。REST Clientを利用しない場合はcurlコマンドやPostmanを利用してください。

REST Clientを利用する場合はプロジェクトフォルダ直下にtest.httpファイルを作成して以下のコードを記述します。


POST http://localhost:8787/
Content-Type: application/json

{
    "name": "John"
}

POSTリクエストを送信すると

POSTリクエストの送信
POSTリクエストの送信

POSTリクエストによるJSONデータの取得方法が確認できました。

天気の取得

ここまでに確認した内容と外部のサービスを利用してリクエストを送信してきた場所の天気を戻すというアプリケーションを作成してみましょう。デプロイするURLがわかればそのURLにアクセスするだけで外出先でも自宅でも自分が現在いる場所の天気を確認することができます。

Request.cfの中にはlongitudeとlatitudeの情報も含まれているのでそれらの情報を利用することでリクエストを行なってきた場所の天気の情報を取得することができます。

アカウントの登録が必要ですが無料で利用できるOpenWeatherサービスのAPIを利用して動作確認を行います。アカウントの取得とAPIの取得については公開済みの下記の文書の”4.OpenWeatherのAPI”を参考にしてください。

latitudeとlongitudeはrequest.cfオブジェクトから取得します。API_KEYについては各自がOpenWeatherサービスから取得した値を設定します。後ほどAPI_KEYは環境変数を設定します。


export default {
  async fetch(request) {
    const lat = request.cf.latitude;
    const lon = request.cf.longitude;
    const API_KEY = 'YOUR_API_KEY';
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}`;
    const response = await fetch(url);
    const data = await response.json();
    return new Response(JSON.stringify(data, null, 2), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};

ブラウザでhttp://localhost:8787にアクセスすると天気の情報を取得することができますがその中のweatherプロパティに現在の天気が含まれています。現在の天気はCloudsなので曇りです。この値を戻すだけで現在の天気が確認できます。


{
  "coord": {
//略
  },
  "weather": [
    {
      "id": 803,
      "main": "Clouds",
      "description": "broken clouds",
      "icon": "04d"
    }
//略

環境変数SECRETを利用した場合

index.jsファイルの中にAPIキーを直接設定していしたがキーの値を隠し環境変数として利用する場合にwrangler secretコマンドで設定を行うことができます。wrangler secretのputの後にはindex.jsで利用していた変数の名前を指定します。コマンドを実行した後は”Enter a secret value”と表示されるのでキーの値を設定してください。


 % wrangler secret put API_KEY
 ⛅️ wrangler 2.0.8 
-------------------
Enter a secret value:  

キーを入れてEnterを押すとキーの設定が行われアップロードされます。アップロードした情報は後ほどCloudflareの管理画面から確認します。


 % wrangler secret put API_KEY
 ⛅️ wrangler 2.0.8 
-------------------
Enter a secret value: ******************************** 
🌀 Creating the secret for script my-worker 
✨ Success! Uploaded secret API_KEY

作成後はコードからAPI_KEYの設定行を削除します。環境変数に設定した値を利用するためにはfetch関数の第二引数から渡されるenvironmentを利用します。


export default {
  async fetch(request, environment) {
    const lat = request.cf.latitude;
    const lon = request.cf.longitude;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${environment.API_KEY}`;
    const response = await fetch(url);
    const data = await response.json();
    return new Response(JSON.stringify(data, null, 2), {
      headers: {
        'content-type': 'application/json',
      },
    });
  },
};

上記のコードは先程と同様jに動作します。設定したsecretキーについてはCloudflareの管理画面から確認することができますが設定したキーの中身を確認することができません。

管理画面上から確認
管理画面上から確認

wrangle.tomlファイルで環境変数

wrangler secretコマンド以外にもwrangler.tomlファイルを利用して環境変数を設定することができます。

下記のように[vars]の下に環境変数API_TOKENを設定します。


name = "my-worker"
main = "src/index.js"
compatibility_date = "2022-06-07"

[vars]
API_TOKEN = "set_environment_variable_in_toml_file"

設定した後はnpm startコマンドを再実行してwrangler.tomlファイルを再読み込みします。

実行するとvarsの値が実行したコンソールに表示されます。


 % npm start

> my-worker@0.0.0 start
> wrangler dev

 ⛅️ wrangler 2.0.8 
-------------------
Your worker has access to the following bindings:
- Vars:
  - API_TOKEN: "set_environment_variable_in_toml_file"
⬣ Listening at http://localhost:8787

ブラウザからlocalhost:8787にアクセスするとenvirnmentオブジェクトの中にAPI_KEYとAPI_TOKENを確認することができます。


Object {
  API_TOKEN: set_environment_variable_in_toml_file,
  API_KEY: 3848acbe15d0148fe86f19ffed49395d
}

API_TOKENにコード中でアクセスしたい場合にはenvironemt.API_TOKENで行うことができます。

天気をHTMLとして表示

天気の情報をJSONデータではなくHTMLのページとして表示する方法を確認しておきます。日本語が文字化けしないようにheadersのcontent-typeにcharsetを設定しています。


const Weather = ({ weather }) => {
  return `
    <html>
      <body>
        <h1>今日の天気は:${weather[0].main}</h1>
      </body>
    </html>
  `;
};

export default {
  async fetch(request, environment) {
    const lat = request.cf.latitude;
    const lon = request.cf.longitude;
    const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${environment.API_KEY}`;
    const response = await fetch(url);
    const data = await response.json();
    return new Response(Weather(data), {
      headers: {
        'content-type': 'text/html;charset=utf-8;',
      },
    });
  },
};

コードを作成後にデプロイを行います。


 % npm run deploy                   

> my-worker@0.0.0 deploy
> wrangler publish

 ⛅️ wrangler 2.0.8 
-------------------
Uploaded my-worker (0.70 sec)
Published my-worker (0.20 sec)
  my-worker.reffect.workers.dev

デプロイ先のmy-workder.reffect.worders.devにアクセスすると天気が表示されます。

天気をHTMLページで表示
天気をHTMLページで表示

アクセスすると現在の天気を表示するだけのシンプルなアプリケーションですがCloudflare Workerを利用して作成することができました。

デプロイ後のログ

デプロイ後にログを確認したい場合はwrangler tailコマンドを利用することができます。


r % wrangler tail            
 ⛅️ wrangler 2.0.8 
-------------------
Successfully created tail, expires at 2021-06-09T12:03:24Z
Connected to my-worker, waiting for logs...

Cloudflare Workersでのデータ保存(KV)

Cloudflare WorkersではKey-Value StoreのWorkers KVを利用することでWokerからのデータの書き込みと読み込みを行うことができます。キーとバリューを利用したシンプルな機能なので設定方法も利用方法も簡単です。

新たにWorkers KV動作用にプロジェクトの作成を行います。ここではkv-workerという名前をつけています。


 % wrangler init kv-worker

Workers KVはwranglerコマンドを利用して行います。KVの名前にはKV_COUNTとつけています。namespaceとしてkv-worker_KV_COUNTが作成されることがわかります。


% wrangler kv:namespace create "KV_COUNT"    
 ⛅️ wrangler 2.0.8 
-------------------
🌀 Creating namespace with title "kv-worker-KV_COUNT"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "KV_COUNT", id = "6adc1e0b10dd4b80b34aff7ced03a353" }

コマンドからWorkersの情報を確認することができます。


 % wrangler kv:namespace list
[
  {
    "id": "d985bb9b930e47ffabd5c4d362929c49",
    "title": "kv-worker-KV_COUNT",
    "supports_url_encoding": true
  }
]

またCloudflareの管理画面にアクセスするとkv_worker_KV_COUNTを確認することができます。

作成したKVの確認
作成したKVの確認

Workers KVに表示されているkv_worker_KV_COUNTの行の右に表示されている”表示”ボタンをクリックすると中身を確認することができます。現在何も入っていないのでキーと値のペアには何も入っていません。この画面からキーと値の設定を行うこともできます。

KVの中身の確認
KVの中身の確認

Workerから作成したKVを利用できるようにwrangler.tomlファイルにwranglerコマンド実行後に表示されていたメッセージを追加します。


kv_namespaces = [
  { binding = "KV_COUNT", id = "6adc1e0b10dd4b80b34afi7ced03a353" }
]

設定が完了したのでWorkerからアクセスする方法を確認します。KVにアクセスするためにはfetch関数の引数から渡されるenvを使います。KVにキーとバリューを保存したい場合はputメソッド、値を取得する場合はgetメソッドを利用します。countというキーに0を設定し、キーを利用して値を取得しています。


export default {
  async fetch(request, env) {
    await env.KV_COUNT.put('count', 0);
    let count = await env.KV_COUNT.get('count');
    return new Response(count);
  },
};

index.jsファイルの更新が完了したら、ローカルで動作確認を行うためにnpm startコマンドを実行します。実行すると下記のようにエラーが発生します。開発と本番では異なるKVを利用するためにKVを作成する際に–previewをつけて新たにKVを作成する必要があります。


 % npm start

> kv-worker@0.0.0 start
> wrangler dev

 ⛅️ wrangler 2.0.8 
-------------------

✘ [ERROR] In development, you should use a separate kv namespace than the one you'd use in production. Please create a new kv namespace with "wrangler kv:namespace create  --preview" and add its id as preview_id to the kv_namespace "KV_COUNT" in your wrangler.toml

ローカル用のKVを作成します。コマンドで指定する名前のKV_COUNTは同じですが–previewをつけているため作成されるnamespaceは”kv-worker-KV_COUNT_preview”となっています。


 % wrangler kv:namespace create KV_COUNT --preview
 ⛅️ wrangler 2.0.8 
-------------------
🌀 Creating namespace with title "kv-worker-KV_COUNT_preview"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
{ binding = "KV_COUNT", preview_id = "d07af49435234b1cb10d6fd70a2f1c50" }

管理画面では追加したKVを確認することができます。

追加したKVの確認
追加したKVの確認

wrangler.tomlファイルに作成したKV Workersの情報を追加します。idは最初に作成した本番用のidを設定します。preview_idには2回目に作成した開発用のidを指定します。


kv_namespaces = [
{ binding = "KV_COUNT", id="6adc1e0a10dd5b80b34aff7ced03a353", preview_id = "d07af49435334b1cb10d6fd70a2f1c50" }
]

npm startコマンドを実行すると利用するKVの情報が表示されます。idがpreview_idになっていることがわかります。


 % npm start                                                     

> kv-worker@0.0.0 start
> wrangler dev

 ⛅️ wrangler 2.0.8 
-------------------
Your worker has access to the following bindings:
- KV Namespaces:
  - KV_COUNT: d07af49435334b1cb10d6fd70a2f1c50
⬣ Listening at http://localhost:8787

npm startコマンドを実行してhttp:://localhost:8787にアクセスすると画面上には”0″が表示されます。Workers KVへの書き込みが成功しました。読み込みにも成功したことがわかります。

次にデプロイを行います。デプロイの場合はidが設定されていることが確認できます。表示されるURLにアクセスするとローカルと同様にブラウザ上に0が表示されます。


 % npm run deploy

> kv-worker@0.0.0 deploy
> wrangler publish

 ⛅️ wrangler 2.0.8 
-------------------
Your worker has access to the following bindings:
- KV Namespaces:
  - KV_COUNT: 6adc1e0a10dd5b80b34aff7ced03a353
Uploaded kv-worker (0.83 sec)
Published kv-worker (3.61 sec)
  kv-worker.reffect.workers.dev

ローカルとデプロイ上ではことなるKVが利用できることも確認できます。

ここまでの動作確認を通してCloudflare Workersの基礎を確認することができました。