天然パーマです。

Cloudflare Workers 面白い

Cloudflare Workers が面白い。面白いので、いくつか簡単なアプリを作ってみた。例えば、そのひとつが Slack Bot で「yusukebe++」とかやるとインクリメントされるやつ。

今回は Cloudflare Workers の面白さについて解説する。より興味のある方がいれば、上記のコードを参考にしてもらうといいだろう。

Cloudflare Workers とは?

Cloudflare の CDN エッジでスクリプトが動くのが Cloudflare Workers。いわゆる serverless の環境である。

追記

強調しておきたいのは、Cloudflare Wokers は serverless に加えて、「CDN のエッジで動くことを前提とした」環境であることだ。その目的と制限を理解しなくてはいけない。大きくて複雑なアプリは作れないし、作るべきではない。


JavaScript か Rust で書ける。他にも PHP と Kotlin とか Perl で書けると書いてあるが、Perl だとJS::inlineで JS 呼んでるだけだったので、まぁ基本 JS と Rust の 2 つと考えていいだろう。

Service Worker の API を踏襲してる。HTTP リクエストをハンドルするためのコードは以下の通りである。

async function handleRequest(request) {
  return new Response("Hello Cloudflare Workers!!!!!!!!", {
    headers: {
      "content-type": "text/plain;charset=UTF-8",
    },
  })
}

addEventListener("fetch", (event) => {
  return event.respondWith(handleRequest(event.request))
})

wranglerという CLI ツールが提供されていて、これを使えば、テンプレートの生成、設定、ビルド、プレビュー、公開が全て手元でできてしまう。他にもminiflareという Yet Another なツールもあったりして開発環境が充実している。

Workers KV

Workers KV という実にシンプルな Key-Value ストアが用意されている。

できるのはget/set/delete相当のものだ。 TTL を設定でき、また値にメタデータを持たせることができる。それに加えて、listという、指定した prefix を Key に持つ値をリストで取得するのがある。でもたったこれだけだ。

これだけだが、逆にシンプルなのがよい。Workers と統合されているため、スクリプトから呼び出しやすくて重宝する。

Workers Site

HTML や画像、CSS などファイルを静的にサーブする機能もある。Cloudflare には Pages という似たようなサービスがあるがそれとはまた別っぽい。

これを利用すれば、Hugo や Gatsby などの SSG や React や Vue などフロントエンドフレームワークをデプロイできる。

その他の機能

条件はあるものの、Cloudflare CDN のキャッシュのコントロールが可能だ。

他にも Websocket が使えたりする。

面白いところ

Cloudflare Workers で面白いと思った点を列挙する。

  • 簡素。GCP や AWS でも severless のアーキテクチャはあるが、個人でパッと使うには複雑すぎる。管理画面もシンプルだ。

  • デプロイまでがすごく楽。wrangler で Starter キットを生成して、wranger publishとすれば、ビルドをして、デプロイが完了する。自動で https://app-name.username.workers.dev といった URL も発行してくれてる。

  • Service Woker の API に寄せている件。ちなみに Deno deploy も Service Woker のそれを採用してて興味深い。
  • Starter テンプレートを使えば、TypeScript で書く環境が一瞬で出来上がる。
  • 最小限のオールインワン。Workers の基本機能で JSON を吐く API を作って、Workers Site にのせた SPA の React から呼び出す、とかをひとつのプロジェクトでできる。
  • CDN と連動させれる。これから紹介するが、CDN のキャッシュをコントロールするために Workers が使える。
  • 速い。実行時間が短く、何よりも CDN エッジで実行されるので、速い。
  • 無料で使える。枠はあるが、個人で遊ぶ分には無料で済んでしまう。
  • 当然ながら、node モジュールが使える。ただし、ビルドした JS が 1MB を超えるとデプロイできないので、ファットなモジュールは避けなくてはいけない。

例: Cloudflare Workers で作ったもの

例として、Cloudflare Wokers で作った 3 つのアプリを紹介する。

PC/Mobile の切り分け

以前からとあるサイトを Cloudflare の CDN にのせているのだが、ユーザーエージェントによって PC 版のページとモバイル版と出し分けをしたい。が、デバイスタイプによるキャッシュはEnterprise plans onlyとなっている。URL 以外をキャッシュキーに含めることができない。

そこで知恵を絞った結果、Workers でできた。以下の Wokers を CDN で動かす。キーを URL とデバイスタイプで生成する。

let isMobile = false
const userAgent = request.headers.get("User-Agent") || ""

if (userAgent.match(/(iPhone|iPod|Android|Mobile)/)) {
  if (!userAgent.match(/(iPad|Table)/)) {
    isMobile = true
  }
}
const device = isMobile ? "Mobile" : "Desktop"

const cacheUrl = new URL(request.url + "-" + device)
const cacheKey = new Request(reqeust.url + device, request)
const cache = caches.default

let response = await cache.match(cacheKey)

ついでに、レスポンスヘッダ s-maxge に TTL を設定して、CDN にキャッシュする時間をスクリプトからコントロールした。

response.headers.append("Cache-Control", "s-maxage=" + ttl)

実用的だ。

Slack Bot

冒頭で紹介した Slack Bot である。

/karma yusukebe++とするとyusukebeという変数がインクリメントされる。逆に yusukebe-- はデクリメントだ。カルマの値はそれぞれ Workers KV にストアされていて、現在の数を返してくれる。

Key-Value ストア向きのアプリなので、何も考えずにできた。以下がKV_KARMAという KV のオブジェクトに対してgetputを実行する。

const karma = async (name: string, operation: string) => {
  const key = PREFIX + name
  const value = await KV_KARMA.get(key)

  let karma = value != null ? parseInt(value) : 0

  if (operation == "++") {
    karma = karma + 1
  } else {
    karma = karma - 1
  }
  await KV_KARMA.put(key, `${karma}`)

  return `${name} : ${karma}`
}

ブックマークアプリ

URL を渡すと OGP 付きで保存。リストで表示してくれるシンプルなブックマークアプリ。ブックマークレットや iOS のショートカットから登録できるようにしてて結構便利。

Workers で KV を利用した Web API を生やして、Workers Site で静的においた React の HTML、JS からそれを呼び出している。API => Frontend という最近っぽい構成がひとつのプラットフォーム完結する、という例である。

まとめ

ちなみ Cloudflare、イケイケで

  • 103 Early Hints
  • Signed Exchange
  • AWS S3 対抗のストレージサービス「R2」

の機能のベータ提供・発表をここ 1 ヶ月以内に立て続けてにやってる。ブログも更新速いので興味深くみている。


ということで Cloudflare Wokers 面白いので、無料なので使ってみるといいだろう。今回は簡単なアプリしか作らなかったが、もっと頑張れるはずだ。さて、最後に断っておくが回し者ではないぞ!