サーバーレス入門。初めてでもわかるCloudflare Workersの書き方からデプロイまで。
Cloudflare WorkersではServerless(サーバレス)な実行環境でJavaScriptのコードを実行することができます。SeverlessということでJavaScriptを実行するサーバなどのインフラの準備、メンテナンスはCloudflareが行うので開発者はコードの作成のみに集中することができます。コードの作成後にデプロイした(Cloudflareにコードをアップロード)コードはある特定の場所にあるデータセンターのサーバに保存されるのではなく世界中に分散するCDNのエッジにデプロイされるため世界中のどこからアクセスしても高速に応答することができます。
本文書では初めてCloudflare Workersを使う人を対象にアカウントの作成からデプロイの方法、シンプルなコードを使ってCloudflareの基本的な利用方法の説明を行なっています。サーバーレスな環境を利用した経験がない人であればCloudflare Workersでは自分で実行環境を構築することもなく作成したコードを簡単にインターネット上に公開することができるのでCloudflare Workersの動作確認を行いながらサーバーレスとは何かも理解できるかと思います。
動作確認はmacOSで行なっています。
目次
Cloudflare Workersアカウントの作成
Cloudflare Workersを利用するためにはアカウントの作成が必要となります。アカウントを作成するためにhttps://workers.cloudflare.com/にアクセスを行い、画面中央にある”Start building”ボタンをクリックするか画面右上にある”Sign up”ボタンをクリックします。
サインアップ画面が表示されるのでEmailアドレスとパスワードを入力します。画面は英語となっていますが言語を変更したい場合には右上にあるEnglish(US)をクリックするとドロップダウンメニューで日本語を選択することができます。
EmailとPasswordを入力後”Create Account”ボタンをクリックします。クリックするとサブドメインを設定する画面が表示されます。サブドメインには任意の名前を入力してください。例えば”my-worker”というWorkerを作成した場合にWorkerを実行するためにアクセスするURLはhttps://my-worker.サブドメイン名.workers.devとなります。入力したら”Set up”ボタンをクリックしてください。
プランの選択画面が表示されます。”Free”と”Paid”プランを2つを選択することができます。1リクエストに対して10msのCPU timeや1日に100,000リクエストという制限がありますが動作確認するためには十分すぎるのでFreeプランを選択します。
プランを選択するとアカウント登録時に入力したEmailにメールが送信されるので確認します。
Cloudlareからメールが届いているか確認を行います。
メールのリンクをCloudflareへのリダイレクトが行われクリックすると認証が完了します。
プロジェクトの作成
新規のプロジェクトを作成したい場合はC3(create-cloudflare-cli)コマンドを実行します。コマンドを実行するとプロジェクト名、TypeScriptの選択、templateの選択、gitを選択、Deployをするか聞かれます。ここではプロジェクト名に”my-worker”, TypeScriptなし、templateは”Hello World Workerno”, gitあり、Deployなしを設定して作成を行います。templateの選択によってプロジェクト作成時に作成されるファイルがかわります。
% npm create cloudflare@latest
> npx
> create-cloudflare
using create-cloudflare version 2.22.3
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./my-worker
│
├ What type of application do you want to create?
│ type "Hello World" Worker
│
├ Do you want to use TypeScript?
│ no typescript
│
├ Copying template files
│ files copied to project directory
│
├ Updating name in `package.json`
│ updated `package.json`
│
├ Installing dependencies
│ installed via `npm install`
│
╰ Application created
╭ Configuring your application for Cloudflare Step 2 of 3
│
├ Retrieving current workerd compatibility date
│ compatibility date 2024-07-25
│
├ Do you want to use git for version control?
│ yes git
│
├ Initializing git repo
│ initialized git
│
├ Committing new files
│ git commit
│
╰ Application configured
╭ Deploy with Cloudflare Step 3 of 3
│
├ Do you want to deploy your application?
│ no deploy via `npm run deploy`
│
├ APPLICATION CREATED Deploy your application with npm run deploy
│
│ Navigate to the new directory cd my-worker
│ Run the development server npm run start
│ Deploy your application npm run deploy
│ Read the documentation https://developers.cloudflare.com/workers
│ Stuck? Join us at https://discord.cloudflare.com
│
╰ See you again soon!
プロジェクトの作成が完了したらプロジェクト名で指定した名前のディレクトリが作成されるので移動します。
% cd my-worker
my-workerディレクトリにはnode_modules、src、testディレクトリの他package.json, package-lock.json,vitest.config.jsとwrangler.tomlファイルが作成されます。srcフォルダの中にはWorkerの実行ファイルであるindex.jsファイルが作成されています。
index.jsではリクエストを受け取るとfetch関数が実行されResponseクラスの引数に設定した”Hello World!”が戻されるといったシンプルなコードです。
export default {
async fetch(request, env, ctx) {
return new Response('Hello World!');
},
};
動作確認
動作確認を行うために”npm run start”コマンドを実行します。npm run startコマンドを実行するとローカル環境で作成したコードの動作確認を行うことができます。キーボードの”b”, “d”, “l”, “c”, “x”キーを利用することでキーに割り当てられた操作を行うことができます。
% npm run start
> my-worker@0.0.0 start
> wrangler dev
⛅️ wrangler 3.67.1
-------------------
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8787
╭──────────────────────────────────────────────────────────────────────╮
│ [b open a [d open [l turn off local [c clear [x to │
│ browser, Devtools, mode, console, exit │
╰──────────────────────────────────────────────────────────────────────╯
“b”を押すとブラウザが起動して”Hello World”が表示されます。ローカル用で利用するポートは8787です。このURLにアクセスするとsrcフォルダのmain.jsの処理が実行されます。
デプロイの方法
ローカルでの動作確認を行うことができたのでデプロイしたい場合は”npm run deploy”コマンドで実行することができます。”npm run start”コマンドを実行している場合は”x”キーをクリックしてローカルサーバを停止してください。
デプロイはCloudflareにログインしていない状態で実行を行います。ログインしている場合はそのままログインした状態で行ってください。
% npm run deploy
> my-worker@0.0.0 deploy
> wrangler deploy
⛅️ wrangler 3.67.1
-------------------
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=54d11594-84e4-41aa-b438-e81b8fa78ee7&redirect_uri=http%3A%2F%2Flocalhost%3A8976%2Foauth%2Fcallback&scope=account%3Aread%20user%3Aread%20workers%3Awrite%20workers_kv%3Awrite%20workers_routes%3Awrite%20workers_scripts%3Awrite%20workers_tail%3Aread%20d1%3Awrite%20pages%3Awrite%20zone%3Aread%20ssl_certs%3Awrite%20ai%3Awrite%20queues%3Awrite%20offline_access&state=..
実行するとブラウザが自動で起動され、Cloudflareのアカウント情報の入力を求められるので入力してください。その後、”Allow Wrangler to make changes to your Cloudflare account?”の確認画面が表示されるので”Allow”ボタンをクリックしてください。
ブラウザの画面には”You have granted authorization to Wrangler!”のメッセージが表示されます。
ターミナルのメッセージにはUploadedとPublished、それとデプロイしたコードを実行するURLが表示されます。
Successfully logged in.
Total Upload: 0.19 KiB / gzip: 0.16 KiB
Uploaded my-worker (2.72 sec)
Published my-worker (3.88 sec)
https://my-worker.reffect.workers.dev
Current Deployment ID: 5604b48-0e5d-47cc-a3dd-4a040791563e
Current Version ID: 5602b48-0e5d-47cc-a3dd-4a040791563e
Note: Deployment ID has been renamed to Version ID. Deployment ID is present to maintain compatibility with the previous behavior of this command. This output will change in a future version of Wrangler. To learn more visit: https://developers.cloudflare.com/workers/configuration/versions-and-deployments
URLにアクセスする前にCloudFlareの管理画面にアクセスしてWorkers&PagesのOverviewのメニューを確認するとデプロイしたmy-workerを確認することができます。
管理画面上からもデプロイしたWorkerを確認することができたのでブラウザからはmy-worker.reffect.workers.devからアクセスを行います。管理画面上のmy-workerの名前の右に表示されているVisitのリンクをクリックしてください。下記のようにhttps://Workerの名前.サブドメイン名.workers.devでアクセスできることがわかります。”Hello World!”と表示されれば問題なく動作していることになります。
ここまでの処理でインターネット上に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 run start”コマンドを実行してローカル環境で動作確認を行います。http://localhost:8787/にアクセスすると定義したuserの内容がJSONで戻されます。
importを利用
index.jsファイル内で定義したuserを別ファイルからimportして利用することも可能です。srcフォルダにdata.jsonファイルを作成します。
{ "name": "John Doe" }
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として表示させるためには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が表示されます。content-typeの設定も重要であることがわかります。
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',
},
});
},
};
設定後ブラウザ上からアクセスを行い確認すると国や都市以外にもさまざまな情報が含まれていることがわかります。
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のExtensionsのREST Clientを利用します。REST Clientをインストールしていない場合は別のExtensionsのThunder ClientやcurlコマンドやPostmanなど使い慣れているツールを利用してください。
REST Clientを利用する場合はプロジェクトフォルダ直下にtest.httpファイルを作成して以下のコードを記述します。
POST http://localhost:8787/
Content-Type: application/json
{
"name": "John"
}
POSTリクエストを送信すると
POSTリクエストによるJSONデータの取得方法が確認できました。
アプリケーションの作成
サーバーレスを利用して何か実行する予定のある人を除いて、ここまでで確認した内容でCloudflare Workersを利用してどんなことができる?という疑問を持っている人も多いかと思います。
動作確認を行なった内容を元に外部のサービスを利用してリクエストを送信してきた場所の天気を戻すというアプリケーションを作成してみましょう。デプロイする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キーを直接設定していましたがキーの値を環境変数として利用する場合にnpx wrangler secretコマンドで設定を行うことができます。wrangler secretのputの後にはindex.jsで利用していた変数の名前を指定します。コマンドを実行した後は”Enter a secret value”と表示されるのでキーの値を設定してください。
% npx wrangler secret put API_KEY
⛅️ wrangler 3.67.1
-------------------
Enter a secret value:
キーを入れてEnterを押すとキーの設定が行われアップロードされます。アップロードした情報は後ほどCloudflareの管理画面から確認します。
% npx wrangler secret put API_KEY
⛅️ wrangler 3.67.1
-------------------
✔ Enter a secret value: … ********************************
🌀 Creating the secret for the Worker "my-worker"
✨ Success! Uploaded secret API_KEY
作成後はコードからAPI_KEYの設定行を削除します。環境変数に設定した値を利用するためにはfetch関数の第二引数から渡されるenvironmentを利用します。
export default {
async fetch(request, env) {
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=${env.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',
},
});
},
};
“npm run deply”でデプロイを行い、動作確認を実行します。
上記のコードは先程と同様に動作します。設定したsecretキーについてはCloudflareの管理画面から確認することができますが設定したキーの中身を確認することができません。
wrangle.tomlファイルで環境変数
wrangler secretコマンド以外にもwrangler.tomlファイルを利用して環境変数を設定することができます。
下記のように[vars]の下に環境変数API_TOKENを設定します。
name = "my-worker"
main = "src/index.js"
compatibility_date = "2024-07-25"
compatibility_flags = ["nodejs_compat"]
[vars]
API_TOKEN = "set_environment_variable_in_toml_file"
設定した後はnpm startコマンドを再実行してwrangler.tomlファイルを再読み込みします。
実行するとvarsの値が実行したコンソールに表示されます。
% npm run start
> my-worker@0.0.0 start
> wrangler dev
⛅️ wrangler 3.67.1
-------------------
Your worker has access to the following bindings:
- Vars:
- API_TOKEN: "set_environment_variable_in_toml_file"
⬣ Listening at http://localhost:8787
set_environment_variable_in_toml_fileの値をAPI_TOKENに設定した値に更新します。
index.jsファイルを更新してAPI_TOKENを指定します。
export default {
async fetch(request, env) {
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=${env.API_TOKEN}`;
const response = await fetch(url);
const data = await response.json();
return new Response(JSON.stringify(data, null, 2), {
headers: {
'content-type': 'application/json',
},
});
},
};
npm run startコマンドを実行してhttp://localhost:8787/にアクセスすると天気の情報が取得できます。
天気を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 deploy
⛅️ wrangler 3.67.1
-------------------
Uploaded my-worker (0.70 sec)
Published my-worker (0.20 sec)
my-worker.reffect.workers.dev
デプロイ先のmy-workder.reffect.worders.devにアクセスすると天気が表示されます。
アクセスすると現在の天気を表示するだけのシンプルなアプリケーションですがCloudflare Workerを利用して作成することができました。
デプロイ後のログ
デプロイ後にログを確認したい場合はwrangler tailコマンドを利用することができます。
% npx wrangler tail
⛅️ wrangler 3.67.1
-------------------
Successfully created tail, expires at 2021-06-09T12:03:24Z
Connected to my-worker, waiting for logs...
アクセスを行うと以下のようにログが表示されます。
% npx wrangler tail
⛅️ wrangler 3.67.1
-------------------
Successfully created tail, expires at 2024-07-29T08:09:35Z
Connected to my-worker, waiting for logs...
GET https://my-worker.reffect.workers.dev/ - Ok @ 2024/7/29 11:10:01
GET https://my-worker.reffect.workers.dev/favicon.ico - Ok @ 2024/7/29 11:10:02
Cloudflare Workersでのデータ保存(KV)
Cloudflare WorkersではKey-Value StoreのWorkers KVを利用することでWokerからのデータの書き込みと読み込みを行うことができます。キーとバリューを利用したシンプルな機能なので設定方法も利用方法も簡単です。
新たにWorkers KV動作用にプロジェクトの作成を行います。ここではkv-workerという名前をつけています。
% npm create cloudflare@latest
//略
using create-cloudflare version 2.22.3
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./kv-worker
//略
Workers KVはwranglerコマンドを利用して行います。KVの名前にはKV_COUNTとつけています。namespaceとしてkv-worker_KV_COUNTが作成されることがわかります。
% npx wrangler kv namespace create "KV_COUNT"
⛅️ wrangler 3.67.1
-------------------
🌀 Creating namespace with title "kv-worker-KV_COUNT"
✨ Success!
Add the following to your configuration file in your kv_namespaces array:
[[kv_namespaces]]
binding = "KV_COUNT"
id = "d8523c606d6a476892d7615c524f4946"
コマンドからWorkersの情報を確認することができます。
% npx wrangler kv namespace list
[
{
"id": "d8523c606d6a476892d7615c524f4946",
"title": "kv-worker-KV_COUNT",
"supports_url_encoding": true
}
]
またCloudflareの管理画面にアクセスするとkv_worker_KV_COUNTを確認することができます。
Workers KVに表示されているkv_worker_KV_COUNTの行の右に表示されている”表示”ボタンをクリックすると中身を確認することができます。現在何も入っていないのでキーと値のペアには何も入っていません。この画面からキーと値の設定を行うこともできます。
Workerから作成したKVを利用できるようにwrangler.tomlファイルにwranglerコマンド実行後に表示されていたメッセージを追加します。
[[kv_namespaces]]
binding = "KV_COUNT"
id = "d8523c606d6a476892d7615c524f4946"
設定が完了したのでWorkerからアクセスする方法を確認します。KVにアクセスするためにはfetch関数の引数から渡されるenvを使います。KVにキーとバリューを保存したい場合はputメソッド、値を取得する場合はgetメソッドを利用します。countというキーに0を設定し、キーを利用して値を取得しています。
export default {
async fetch(request, env) {
await env.KV_COUNT.put('count', 10);
let count = await env.KV_COUNT.get('count');
return new Response(count);
},
};
index.jsファイルの更新が完了したら、ローカルで動作確認を行うためにnpm run startコマンドを実行します。管理画面では追加したKVを確認することができます。
npm startコマンドを実行してhttp:://localhost:8787にアクセスすると画面上には”10″が表示されます。Workers KVへの書き込みが成功しました。読み込みにも成功したことがわかります。
次にデプロイを行います。デプロイの場合はidが設定されていることが確認できます。
% npm run deploy
> kv-worker@0.0.0 deploy
> wrangler deploy
⛅️ wrangler 3.67.1
-------------------
Total Upload: 0.26 KiB / gzip: 0.19 KiB
Your worker has access to the following bindings:
- KV Namespaces:
- KV_COUNT: d8523c606d6a476892c7615b524f4946
Uploaded kv-worker (1.74 sec)
Published kv-worker (4.03 sec)
https://kv-worker.reffect.workers.dev
//略
表示されるURLにアクセスするとローカルと同様にブラウザ上に10が表示されます。
ローカルとデプロイ上ではことなるKVが利用できることも確認できます。
ここまでの動作確認を通してCloudflare Workersの基礎を確認することができました。