Notes

Sat Dec 05 2020Cloudflare Workers + GitHub issues でブログ配信

yo_waka さんが Cloudflare Workers で興味深いことをやっていたので、自分もそれに習ってブログを作ってみた。
元ネタはこちら: 2020-11-08 このブログの実装 2020年版

概要

GitHub issuesに作成した issue の内容を、Cloudflare Workers の仕組みを利用して配信する仕組み。
Cloudflare Workers は Cloudflare が提供する CDN のエッジにおいて Javascript を実行してレスポンスを返すもので、アクセスするユーザーは自身のブラウザから一番近いCDNのエッジにアクセスしてレスポンスを得られるため、network latency を最小限に抑えることができる。

当然CDNなので静的ファイルのキャッシュ、独自ドメインの利用可、Cloudflareが提供する証明書の利用可など恩恵が受けられる。また安価であり、アクセス数が一定以下であればフリープランが使えるので個人でなにかコンテンツを配信するのもお手軽にできるのがありがたい。

Cloudflare Workers

CDNのエッジに実装された Service Worker にて、Javascript を実行して返すもの。Service Worker の詳細の説明については省くが、本来ブラウザで実装されるもので、オンラインのコンテンツをキャッシュしたり、オフライン環境でコンテンツ提供したりなど、アプリケーションレイヤにおけるローカルプロキシのような働きをする(この表現はスコープを狭くしてしまって微妙かもしれない)。

Cloudflare Workers は、元々はService Workerではなく、JavaScriptの実行環境と独自のフック機能の提供を考えていたらしいが、Service Workerの想定しているユースケースに合致している部分が多かったため、Service Workerを実装したとのこと(このあたりあまり詳しく調べていないのとエッジコンピューティングについて理解があまりないので詳しい説明はしない)。

同じようなサービスに、Lambda@Edge や Fastly Compute@Edge、Akamai EdgeWorkers などがある。

Example

Cloudflare Workers の利用例は https://developers.cloudflare.com/workers/examples に載っている。

HTMLやJsonのようなコンテンツを返すレイヤ、Redirect、A/B testing や Casheなどプロキシとしての役割を果たすものなど多くの例の記載がある。

Wrangler

Cloudflare Workers を利用する場合は wrangler という CLI ツールが用意されているので、始めるのがとても簡単。Docも充実しているTutorialも用意されているのでここを試せば一通り使えるようになる。

Workers KV

Cloudflare Workers から利用できる Datastore として、Workers KV という KeyValue Store が用意されている。

使い方は単純で、<KVNamespace>.get<KVNamespace>.set で利用可能。

import { handleRequest as handleOriginRequest } from './router';
import { Config, Response } from './types';

declare const CACHED_RESPONSE: KVNamespace;

/**
 * Use Cloudflare Workers KV Namespace.
 */
const handleRequest = async (uri: string, config: Config): Promise<Response> => {
  const cacheKey = (new URL(uri)).pathname;
  const cache: Response | null = await CACHED_RESPONSE.get(cacheKey, 'json');
  if (cache) {
    return cache; // use cache
  }

  const response = await handleOriginRequest(uri, config);
  // put cache if contents exists
  if (response.status === 200) {
    await CACHED_RESPONSE.put(cacheKey, JSON.stringify(response));
  }

  return response;
};

export { handleRequest };

https://github.com/foostan/notes/blob/main/src/proxy.ts

本番用とpreview用でそれぞれ用意して使い分けている

image

GitHub Actions

元ネタのままだが、コード修正後の push で本番デプロイ、ブログの記事の元データとなる issue を書いて、label を付けた(消した)アクションをフックして、再キャッシュ処理が走る。

issue に public label を付けて公開されるまで 30s ぐらい。
https://github.com/foostan/notes/actions/runs/429607256

Performance

Lighthouse

すべて100%
image

Network

いずれも25ms以内に返ってきている
image