Cloudflare Workers を Rust で使う

Cloudflare Workers を Rust で使ってみたメモです。最小限のコードで、セットアップからデプロイまで行ってみました👍🏻

準備

wrangler, wasm-pack をインストール

cargo install wrangler wasm-pack

wrangler login

wrangler login

ここで Cloudflare の画面が開いて認証を許可する画面が出るが、上手く行かなかったです。GitHub の Issues にもあがってて、手動でやるのが良さそうです。

仕方ないので、API Token を手動で発行し、手動で設定しました。

wrangler config

認証に成功すると、 wrangler whoamiaccount_id が取れるようになります。また、 Cloudflare のコンソールで、デプロイ先の zone_id をあわせてメモしておきます。

アプリケーションのセットアップ

wrangler generate

wrangler generate first-project https://github.com/cloudflare/rustwasm-worker-template/

で、 ./first-project にテンプレートをベースにしたプロジェクトが作成されます。この状態で build & publish 可能です。

src/lib.rs を試しに編集してみます。
#[wasm_bindgen] は WebAssembly として Rust のコードを JS 側から呼び出せるようにするためのものです。

#[wasm_bindgen]
pub fn greet() -> String {
    "こんにちは!".to_string()
}

これがどのように使われているかと言うと、 worker/worker.js 内で呼ばれていて、

const { greet } = wasm_bindgen;
await wasm_bindgen(wasm)
const greeting = greet()

として、 Rust の関数が JS 内から呼び出されています。

addEventListener('fetch', ...

は、Cloudflare の Worker にリクエストがあったときに発生するイベントで、ここがエントリーポイントになります。

wrangler.toml を編集

wrangler.toml 内で、先ほどメモしておいた account_id, zone_id を設定します。

ビルド確認

wasm-pack build

でビルドします。

Error: wasm32-unknown-unknown target not found in sysroot: ... のエラーが出た時は、 target を追加すればOKです。

rustup target add wasm32-unknown-unknown

その後、ビルドが通ることを確認します。

wasm-pack build

動作確認

wrangler preview --watch

を実行すると、ターミナル上に

Opened a link in your default browser: https://cloudflareworkers.com/?wrangler_session_id=....

と表示され、デフォルトブラウザが開きます。

あとは、コードを変更すると自動的にコンパイルしてブラウザ上で最新コードの動作が反映されます。

デプロイ

wrangler.toml で、routing を記述できる。

route = "ecpplus.net/wasm/hello"

のように設定すると、自動的に https://ecpplus.net/wasm/hello の URL に worker をマッピングしてくれます。サブドメインに割り振る事もできましたが、DNSにサブドメインのレコードが存在している事が必要でした。 CNAME を設定しておくだけでも動きましたが、それだと他のパスも一緒にマッピングされてしまうので、他に良い方法がありそうな気がします。


Cloudflare で既に管理されているドメインであれば、ほぼゼロコンフィグでコードを書き始められるので、簡単な機能ならサクッとデプロイまで出来そうです。

Cloudflare Worker の機能として、KVS, Cache, 永続化Object などがあるので、 Worker とこれらの機能だけでも簡単なアプリケーションも出来そうです。ただ、Cloudflare は基本 CDN なので、そのような用途で Worker を使うのが良さそうでした。