Denoflareを使ってCloudflare WorkersをTypescriptで実装する

2022.06.03

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

Introduction

先日書いたこの記事では、
Cloudflare Workers公式のCLIツールであるWranglerを使って
RustのWorkersをデプロイしました。

今回はWorkersをTypeScriptで書きたいと思い、
いい方法がないか探していたところ、Denoflareという、
DenoをつかってCloudflare Workersの開発やデプロイを実施するためのツールを見つけました。
これを使えば自分でwebpack使ったりesbuild使ったりして
ごにょごにょする必要ががなくなります。

また、Denoflareを使うなら、wrangler/node/webpackなどは必要ありません。
※Denoは必要ですが

ではDenoflareのインストールからWorkersのへpublishまでやってみましょう。

Denoflare?

Denoflareは、Cloudflare Workersの開発やデプロイを簡単にするCLIツールです。
特徴はここにあります。

以下要約。

  • ローカルでの開発/テストが簡単(denoflare serve)
  • TypeScriptのWorkersモジュールを簡単にCloudflareにデプロイ(denoflare push)
  • production用のWorkersをCLIから監視(denoflare tail)
  • Cloudflare Pagesのstati siteを生成(denoflare site)

あと、Cloudflare Rest APIが呼べたり
R2ストレージ操作ができたり、durable-objects/R2のコスト統計がみれたりします。

Environment

  • MacBook Pro (13-inch, M1, 2020)
  • OS : MacOS 11.3.1
  • Deno : 1.22.0

Setup

まずはDenoのインストール。

% curl -fsSL https://deno.land/x/install/install.sh | sh

・・・

% deno --version
deno 1.22.0 (release, aarch64-apple-darwin)
v8 10.0.139.17
typescript 4.6.2

参考:https://deno.land/manual@v1.22.0/getting_started/installation

続いてDenoflareのインストール。

% deno install --unstable --allow-read --allow-net --allow-env --allow-run --name denoflare --force \
https://raw.githubusercontent.com/skymethod/denoflare/v0.5.1/cli/cli.ts

✅ Successfully installed denoflare
/path/your/.deno/bin/denoflare
ℹ️  Add /path/your/.deno/bin to PATH
    export PATH="/path/your/.deno/bin:$PATH"

自分の場合はzshrcに.deno/binパスを追加しました。

% denoflare --help
denoflare 0.5.1

USAGE:
    denoflare <command> <args> <options>
・・・

これでインストールOKです。

Create Cloudflare Workers

適当なディレクトリをつくってそこにDenoflareの設定ファイル(.denoflare)を作成。

// .denoflare
{
    "$schema": "https://raw.githubusercontent.com/skymethod/denoflare/v0.5.1/common/config.schema.json",
    "scripts": {
        "hello-denoflare": {
            "path": "index.ts",
            "bindings": {
                "SUFFIX": {
                    "value": "is a genius!"
                }
            },
            "localPort": 3030
        }
    },
    "profiles": {
        "account1": {
            // your cloudflare account id
            "accountId": "<YOUR ACCOUNT ID>",
            // your cloudflare api token
            "apiToken": "<YOUR API TOKEN>"
        }
    }
}

scriptsでWorkersの定義を行います。
また、bindingsを使うとWorkers内で参照したい値をバインドすることができます。
↑の場合、ts内で「${env.SUFFIX}」とすればvalueが参照可能です。

accountId idはCloudflare Workersのダッシュボード右側で確認できます。
また、api tokenはここで作成可能なので、
取得してそれぞれ記述しておきましょう。

次にWorkersで動かしたいモジュールのtsを作成。

// index.ts
export default {
    async fetch(request: Request, env: any) {
        const url = new URL(request.url)
        const search = new URLSearchParams(url.search)
        const name = search.get('name') || 'Somebody'

        try {
            return new Response(`${name} ${env.SUFFIX}`)
        } catch (e) {
            return new Response(e.message)
        }
    },
}

クエリパラメータ(name)から値を取得して文字列を返すだけです。
serveコマンドを使うとローカルで動作確認できます。

% denoflare serve hello-denoflare
Compiling https://raw.githubusercontent.com/skymethod/denoflare/v0.5.1/cli-webworker/worker.ts into worker contents...
Bundled https://raw.githubusercontent.com/skymethod/denoflare/v0.5.1/cli-webworker/worker.ts (process) in 605ms
runScript: index.ts
Bundled index.ts (process) in 217ms
worker: start
Started in 850ms (isolation=isolate)
Local server running on http://localhost:3030

curlで動作確認。
なお、index.tsを変更して保存すれば、そのまま変更が反映されます。

% curl -i http://localhost:3030/\?name\=syuta
HTTP/1.1 200 OK
content-type: text/plain;charset=UTF-8
vary: Accept-Encoding
content-length: 18
date: Fri, 03 Jun 2022 03:31:28 GMT

syuta is a genius!%

Workersへpush

ローカルで動いたので、Cloudflareにデプロイしてみます。
pushコマンドで名前を指定すればアップロード。

% denoflare push hello-denoflare
bundling hello-denoflare into bundle.js...
bundle finished (process) in 234ms
computed bindings in 0ms
putting module-based worker hello-denoflare... (539bytes) (308bytes compressed)
put script hello-denoflare in 1136ms

ここでCloudflareのダッシュボードみると
hello-denoflareのworkersができていることがわかります。
また、↓のようにすれば別の名前をつけることもできます。

% denoflare push <.denoflareでのscriptの名前> --name <Workersでつけたい名前>

ただ、pushしただけだとアクセスできないので、
Workersのトリガーで、ルートを有効にする必要があります。

ちなみに、denoflare push時に --watch をつけると、
スクリプトファイルが変更されるタイミングで自動的にpushしてくれます。

denoflare tail

denoflare tailコマンドを使うと、
CloudflareにあるWorkerのログストリームを表示してくれます。

% denoflare tail hello-denoflare --format pretty
creating tail...
Connected! Streaming logs from mydenoflare... (ctrl-c to quit)
[2022-06-03 11:12:32] [KIX] [Ok] GET https://mydenoflare.classmthod-nakamura-shuta.workers.dev/?name=syuta
 | [res] 200
[2022-06-03 11:12:32] [KIX] [Ok] GET https://mydenoflare.classmthod-nakamura-shuta.workers.dev/favicon.ico

format json(デフォルト)にするとけっこうな量のログが出るので注意。

その他機能

Denoflareには他にも便利な機能があります。
denoflare siteコマンドを使うと、
静的なドキュメントをCloudflare Pagesでホストすることができます。
あとはdenoflare r2でR2操作(バケットの操作とかファイルのアップロード・ダウンロードとか)   もできます。
使い方については各種ドキュメントをご確認ください。

Summary

今回はCloudflare WorkersをTypescriptで簡単に管理するためのCLIツール、
Denoflareについて紹介しました。
TypeScriptでWorkersを書く場合、簡単に使えていい感じです。
Wranglerと適宜使い分けながらWorkers管理をしていきましょう。