チュートリアル動画にしたがってCloudflare Workersを使ってみた

チュートリアル動画にしたがってCloudflare Workersを使ってみた

2024.07.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんちには。

データ事業本部 インテグレーション部 機械学習チームの中村( @nokomoro3 )です。

本記事では以下の記事に引き続き、Cloudflare Workersを触ってみたいと思います。

https://dev.classmethod.jp/articles/vite-project-deploy-cloudflare-pages/

以下の公式YouTubeを参考にしており、半分くらい(32:50)のところまでの内容を本記事で扱っています。

https://www.youtube.com/watch?v=H7Qe96fqg1M

Cloudflare Workersとは

Cloudflare Workersは、Cloudflareが提供するサーバーレスのエッジコンピューティングプラットフォームです。
APIの作成やコンテンツの動的生成や変更などが可能で、Cloudflareの他のサービス(KV、D1データベース、R2ストレージなど)との統合も可能です。
従来のサーバーサイドプログラミングの多くのユースケースをカバーしつつ、エッジコンピューティングの利点を活かした高性能なアプリケーション開発を可能にします。

使用環境

Windows 10のホスト側で作業します。
また各コマンドはPowershellを使って実行しています。

事前準備

以下を事前に実施しておく前提です。

npmをpnpmにするとコケることがありましたので、npmを使っています。

使ってみた

プロジェクトの作成

以下を実行すると設定値について聞かれますので、ターミナルで入力をして進めます。

npm create cloudflare

プロジェクト名(アプリケーション名)を設定します。

 In which directory do you want to create your application? also used as application name
  ./workers-getting-started

Workerのタイプを選択します。Pythonもあるようですが、今回はグッとこらえてオーソドックスな一番上の「"Hello World" Worker」を選択します。

 What type of application do you want to create?
  ● "Hello World" Worker
  ○ "Hello World" Worker (Python)
  ○ Website or web app
  ○ Example router & proxy Worker
  ○ Scheduled Worker (Cron Trigger)
  ○ Queue consumer & producer Worker
  ○ Co-ordination / multiplayer API (using Durable Objects)
  ○ API starter (OpenAPI compliant)
  ○ Worker built from a template hosted in a git repository

TypeScriptは「Yes」を選択します。

 Do you want to use TypeScript?
  Yes / No

Gitによるバージョン管理も「Yes」にしておきます。

 Do you want to use git for version control?
  Yes / No

デプロイは手動で行いたいですので、以下は一旦Noとしておきます。

 Do you want to deploy your application?
  Yes / No

最終的には以下のようにターミナルに表示されました。

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 ./workers-getting-started

 What type of application do you want to create?
 type "Hello World" Worker

 Do you want to use TypeScript?
 yes 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

 Installing @cloudflare/workers-types
 installed via npm

 Adding latest types to `tsconfig.json`
 added @cloudflare/workers-types/2023-07-01

 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 workers-getting-started
 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!

作成されたプロジェクトには以下のようなファイル・ディレクトリが格納されています。

node_modules/
src/
test/
.editorconfig
.prettierrc
package-lock.json
package.json
tsconfig.json
vitest.config.mts
worker-configuration.d.ts
wrangler.toml

package.jsonscript のところを確認すると、 wrangler というコマンドで操作されていることが分かります。

{
  "name": "workers-getting-started",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "deploy": "wrangler deploy",
    "dev": "wrangler dev",
    "start": "wrangler dev",
    "test": "vitest",
    "cf-typegen": "wrangler types"
  },
  "devDependencies": {
    "@cloudflare/vitest-pool-workers": "^0.4.5",
    "@cloudflare/workers-types": "^4.20240725.0",
    "typescript": "^5.5.2",
    "vitest": "1.5.0",
    "wrangler": "^3.60.3"
  }
}

wranglerとは

wranglerはCloudflareのアプリケーションを管理するためのコマンドラインツールで、Workers、Pages以外にもD1やR2、KVなども管理できます。

npx wrangler を実行すれば各操作を実行することができます。

npx wrangler help

# wrangler
# 
# COMMANDS
#   wrangler docs [command]            📚 Open Wrangler's command documentation in your browser
# 
#   wrangler init [name]               📥 Initialize a basic Worker
#   wrangler dev [script]              👂 Start a local server for developing your Worker
#   wrangler deploy [script]           🆙 Deploy a Worker to Cloudflare  [aliases: publish]
#   wrangler deployments               🚢 List and view the current and past deployments for your Worker [open beta]
#   wrangler rollback [deployment-id]  🔙 Rollback a deployment for a Worker [open beta]
#   wrangler delete [script]           🗑  Delete a Worker from Cloudflare
#   wrangler tail [worker]             🦚 Start a log tailing session for a Worker
#   wrangler secret                    🤫 Generate a secret that can be referenced in a Worker
#   wrangler types [path]              📝 Generate types from bindings and module rules in configuration
# 
#   wrangler kv                        🗂️  Manage Workers KV Namespaces
#   wrangler queues                    🇶  Manage Workers Queues
#   wrangler r2                        📦 Manage R2 buckets & objects
#   wrangler d1                        🗄  Manage Workers D1 databases
#   wrangler vectorize                 🧮 Manage Vectorize indexes [open beta]
#   wrangler hyperdrive                🚀 Manage Hyperdrive databases
#   wrangler pages                     ⚡️ Configure Cloudflare Pages
#   wrangler mtls-certificate          🪪  Manage certificates used for mTLS connections
#   wrangler pubsub                    📮 Manage Pub/Sub brokers [private beta]
#   wrangler dispatch-namespace        🏗️  Manage dispatch namespaces
#   wrangler ai                        🤖 Manage AI models
# 
#   wrangler login                     🔓 Login to Cloudflare
#   wrangler logout                    🚪 Logout from Cloudflare
#   wrangler whoami                    🕵️  Retrieve your user information
# 
# GLOBAL FLAGS
#   -j, --experimental-json-config  Experimental: support wrangler.json  [boolean]
#   -c, --config                    Path to .toml configuration file  [string]
#   -e, --env                       Environment to use for operations and .env files  [string]
#   -h, --help                      Show help  [boolean]
#   -v, --version                   Show version number  [boolean]
# 
# Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose

wranglerを使ってCloudflareにログイン

アプリケーションをデプロイするためには、ログインが必要です。以下のコマンドを実行します。

npx wrangler login

#  ⛅️ wrangler 3.67.1
# -------------------
# 
# Attempting to login via OAuth...
# Opening a link in your default browser: ...(以降略)

するとブラウザ側に遷移するので、問題なければ以下の「Allow」を押下します。

get-start-cloudflare-workers_2024-07-30-12-02-41

以下の画面が出ればOKです。こちらのタブは閉じてしまって大丈夫です。

get-start-cloudflare-workers_2024-07-30-12-03-58

ターミナル側に戻ると「Successfully logged in.」と表示されていると思います。

ログインに失敗する場合は以下の対応を試してみてください(私はここでハマりました)。

https://blog.y-yuki.net/entry/2021/04/18/003000

ログイン後は、ログイン状況を以下のコマンドで確認できます。

npx wrangler whoami

#  ⛅️ wrangler 3.67.1
# -------------------
# 
# Getting User settings...
# 👋 You are logged in with an OAuth Token, associated with the email ****!
# ┌─────────────────────────────────────────┬──────────────────────────────────┐
# │ Account Name                            │ Account ID                       │
# ├─────────────────────────────────────────┼──────────────────────────────────┤
# │ ****                                    │ ****                             │
# └─────────────────────────────────────────┴──────────────────────────────────┘
# 🔓 Token Permissions: If scopes are missing, you may need to logout and re-login.
# Scope (Access)
# - account (read)
# - user (read)
# - workers (write)
# - workers_kv (write)
# - workers_routes (write)
# - workers_scripts (write)
# - workers_tail (read)
# - d1 (write)
# - pages (write)
# - zone (read)
# - ssl_certs (write)
# - ai (write)
# - queues (write)
# - offline_access

デプロイ

ログインすると、アプリケーションのデプロイを行うことができます。

npm run deploy

# > workers-getting-started@0.0.0 deploy
# > wrangler deploy
# 
# 
#  ⛅️ wrangler 3.67.1
# -------------------
# 
# Total Upload: 0.19 KiB / gzip: 0.16 KiB
# Uploaded workers-getting-started (1.22 sec)
# Published workers-getting-started (3.85 sec)
#   https://***
# Current Deployment ID: ****
# Current Version ID: ****
# 
# 
# 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にアクセスすると、Hello Worldを確認することができました。

get-start-cloudflare-workers_2024-07-30-12-10-54

Cloudflareの管理コンソールでもアプリケーションが作成されていることが確認できます。

get-start-cloudflare-workers_2024-07-30-12-14-12

開発用サーバーの起動

開発用サーバーを起動する方法も確認しておきます。

npm start

# > workers-getting-started@0.0.0 start
# > wrangler dev
# 
# 
#  ⛅️ wrangler 3.67.1
# -------------------
# 
# ⎔ Starting local server...
# [wrangler:inf] Ready on http://127.0.0.1:8787
# ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
# │ [b] open a browser, [d] open Devtools, [l] turn off local mode, [c] clear console, [x] to exit  
# ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

http://127.0.0.1:8787 にアクセスすると、ローカル開発サーバーにアクセスできます。実際にはminiflareと呼ばれるツールを使ってローカル開発サーバーをセットアップしているようです。
miniflareはオープンソースのJavaScriptランタイムであり、以下から確認することができます。

https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare

コードの編集

アプリケーションのメインは src/index.ts にあります。以下のレスポンスが今ブラウザに表示されています。

src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		return new Response('Hello World!');
	},
} satisfies ExportedHandler<Env>;

Hello World を変更し、開発サーバーをリロードすると、レスポンスが書き変わっていることが分かります。

src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		return new Response('Hello, Youtube!');
	},
} satisfies ExportedHandler<Env>;

ローカルモードのオフ

ローカル環境では、Cloudflareの他サービス(D1やKVなど)にアクセスするような動作確認が難しいのですが、ローカルモードをオフにすることでCloudflare固有のプレビューサーバーでテストバージョンを動かすようなことが可能です。

ローカル開発サーバーを動かしている状態で以下のようなメッセージが出ていると思いますが、ここで l キーを押下します。

# ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
# │ [b] open a browser, [d] open Devtools, [l] turn off local mode, [c] clear console, [x] to exit  
# ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

 Shutting down local server...
Total Upload: 5.42 KiB / gzip: 1.73 KiB

この設定だけで、プレビューサーバーで動作するように変わっています。

実際ブラウザの開発ツールでレスポンスヘッダを確認すると、元々は以下でしたが、

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/plain;charset=UTF-8
Content-Encoding: gzip

ローカルモードをオフとすると以下のように CF-RAY が付与されたり Server: cloudflare に変化しています。CF-RAYはリクエストの一意の識別子のようなものとなっています。

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Date: Tue, 30 Jul 2024 03:41:12 GMT
Content-Type: text/plain;charset=UTF-8
Content-Encoding: gzip
Server: cloudflare
Vary: Accept-Encoding
alt-svc: h3=":443"; ma=86400
CF-RAY: 8ab254e6ab5046b5-SIN
...(以降略)

リクエストのダンプ

コード上でリクエストに関する詳細情報をダンプすることもできます。

src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		console.log(JSON.stringify(request.cf))
		return new Response('Hello, Youtube!');
	},
} satisfies ExportedHandler<Env>;

ローカルサーバーの標準出力としてターミナルから以下のように取得できます。

{
    "clientTcpRtt": 7,
    "longitude": "***",
    "httpProtocol": "HTTP/1.1",
    "tlsCipher": "AEAD-AES256-GCM-SHA384",
    "continent": "AS",
    "asn": 2518,
    "clientAcceptEncoding": "gzip, deflate, br, zstd",
    "country": "JP",
    "verifiedBotCategory": "",
    "tlsClientAuth": {
        "certIssuerDNLegacy": "",
        "certIssuerSKI": "",
        "certSubjectDNRFC2253": "",
        "certSubjectDNLegacy": "",
        "certFingerprintSHA256": "",
        "certNotBefore": "",
        "certSKI": "",
        "certSerial": "",
        "certIssuerDN": "",
        "certVerified": "NONE",
        "certNotAfter": "",
        "certSubjectDN": "",
        "certPresented": "0",
        "certRevoked": "0",
        "certIssuerSerial": "",
        "certIssuerDNRFC2253": "",
        "certFingerprintSHA1": ""
    },
    "tlsExportedAuthenticator": {
        "clientFinished": "****",
        "clientHandshake": "****",
        "serverHandshake": "****",
        "serverFinished": "****"
    },
    "tlsVersion": "TLSv1.3",
    "city": "Tokyo",
    "timezone": "Asia/Tokyo",
    "colo": "NRT",
    "tlsClientHelloLength": "386",
    "edgeRequestKeepAliveStatus": 1,
    "postalCode": "****",
    "region": "Tokyo",
    "latitude": "****",
    "requestPriority": "",
    "regionCode": "13",
    "asOrganization": "****",
    "tlsClientExtensionsSha1": "****",
    "tlsClientRandom": "****",
    "botManagement": {
        "corporateProxy": false,
        "verifiedBot": false,
        "jsDetection": {
            "passed": false
        },
        "staticResource": false,
        "detectionIds": {},
        "score": 99
    }
}

postalCodeやISPなどの情報を確認することができます。

動画内でも botManagement というオブジェクトは興味深いものとして取り上げられており、この中の score でボットかどうかを判断する材料とすることができます。(99は99%の確率でボットではないという意味です)

Bindingsについて

動画内では、 export interface Env というものがメインのコードにあるようですが、現状は worker-configuration.d.ts という別ファイルに定義されています。

worker-configuration.d.ts
// Generated by Wrangler
// After adding bindings to `wrangler.toml`, regenerate this interface via `npm run cf-typegen`
interface Env {
}
src/index.ts
/**
 * Welcome to Cloudflare Workers! This is your first worker.
 *
 * - Run `npm run dev` in your terminal to start a development server
 * - Open a browser tab at http://localhost:8787/ to see your worker in action
 * - Run `npm run deploy` to publish your worker
 *
 * Bind resources to your worker in `wrangler.toml`. After adding bindings, a type definition for the
 * `Env` object can be regenerated with `npm run cf-typegen`.
 *
 * Learn more at https://developers.cloudflare.com/workers/
 */

export default {
	async fetch(request, env, ctx): Promise<Response> {
		console.log(JSON.stringify(request.cf))
		return new Response('Hello, Youtube!');
	},
} satisfies ExportedHandler<Env>;

公式ドキュメントで使い方を確認してみます。

https://developers.cloudflare.com/workers/runtime-apis/bindings/

EnvはBindingsに使用されるもので、Workersから他のCloudflareのサービスに接続するためのオブジェクトで、以下に記載がありました。

たとえばR2バケットを使用したい場合は、まず wrangler.toml に以下のように記載し、

main = "./src/index.js"
r2_buckets = [
  { binding = "MY_BUCKET", bucket_name = "<MY_BUCKET_NAME>" }
]

その後、コード側で env オブジェクトを使って以下のように env.MY_BUCKET という形でアクセスできるようになるようです。

export default {
  async fetch(request, env) {
    const key = url.pathname.slice(1);
    await env.MY_BUCKET.put(key, request.body);
    return new Response(`Put ${key} successfully!`);
  }
}

Handlersについて

生成されたコードでは fetch というメソッドが定義されていますが、これはFetch Handlerと言われるもので、これ以外にも様々なHandlerを記述することができます。

https://developers.cloudflare.com/workers/runtime-apis/handlers/

Handlerは外部入力を受け取って処理するWorkerのメソッドで、Workerの外部から呼び出すことができます。

例えばFetch HandlerはHTTPリクエストを受け取り、レスポンスを返すことができます。

その他にもスケジュールされた処理を扱うScheduled Handlerなどがあります。

export default {
  async scheduled(event, env, ctx) {
    ctx.waitUntil(doSomeTaskOnASchedule());
  },
}

JSONレスポンスを返す方法

JSONのレスポンスをFetch Handlerで返すには以下のように記載します。

src/index.ts
export default {
	async fetch(request, env, ctx): Promise<Response> {
		return new Response(JSON.stringify({ hello: "World" }), {
			headers: {
				'Content-Type': 'application/json'
			}
		});
	},
} satisfies ExportedHandler<Env>;

これらはHonoというフレームワークを使えば、より簡単に実行できるようですが、今回はベーシックな方法で試してみます。

最後にデプロイして動作確認をします。

npm run deploy

get-start-cloudflare-workers_2024-07-30-17-43-26

CLIからもアクセスしてみます。

curl {デプロイ先URL} | jq

#   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#                                  Dload  Upload   Total   Spent    Left  Speed  
# 100    17  100    17    0     0     33      0 --:--:-- --:--:-- --:--:--    33 
# {
#   "hello": "World"
# }

ただしくリクエストが取得できていることがわかりました。

wrangler.tomlについて

wrangler.toml にはWorkersアプリケーションの様々な設定を記載することができます。

wrangler.toml
#:schema node_modules/wrangler/config-schema.json
name = "workers-getting-started"
main = "src/index.ts"
compatibility_date = "2024-07-25"
compatibility_flags = ["nodejs_compat"]

name はアプリケーション名、 main はアプリケーションのメインファイルを指定することができます。

compatibility_date は互換性を保つための情報で、動画内でも最も重要な情報と説明されています。
プロジェクトのWorkersのランタイムバージョンを管理するためのもので、特定の日付のバージョンにランタイムをロックするような動作をします。

この設定値やランタイムのChange historyについては以下にも記載されているので、詳細は以下をご確認ください。

https://developers.cloudflare.com/workers/configuration/compatibility-dates/

まとめ

いかがでしたでしょうか。この動画の続きはHonoフレームワークを使ったもののようですので、こちらも引き続き記事にできたらと思っています。

本記事がCloudflare Workersをお使いになる方の参考になれば幸いです。

この記事をシェアする

FacebookHatena blogX

関連記事