Cloudflare Workersのチュートリアルをやってみた

2019.10.24

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

はじめに

CX事業本部@札幌の佐藤です。

10/21(月) 〜 10/22(火)で開催された Serverless Days Tokyo 2019に参加してきました。そこで、Cloudflare WorkersというCloudflare社が提供しているサーバーレスサービスの説明とデモのセッションがありました。私自身今回のセッションで初めて聞いたサービスであるのと、セッションだけだと概要しかわからなかったため、実際に動作させてどのようなサービスかを理解しようと思いました。

https://dev.classmethod.jp/etc/serverlessdays-2019-all-you-need-is-javascript/の記事の続きです。

Cloudflare Workersとは

Cloudflare Workersとは、Cloudflare社が提供するCDN(コンテンツデリバリーネットワーク)のエッジで開発者がJavaScriptを実行できるサーバーレスなサービスです。JavaScriptのコードを15秒以内に90カ国194の都市にデプロイし、世界中のユーザーから数ミリ秒以内にコードが実行されるとのことです。また、Lambdaなどのサーバーレスサービスの問題ともいえるコールドスタート問題ですが、Cloudflare Workersでは他のサーバーレスプラットフォームよりコールドスタートのスループットが最大50倍高速となっています。

環境構築

Cloudflare Workersを動かすための環境構築を行います。

Cloudflare Workersのアカウントを作成

  • 以下のサイトにアクセスします

https://workers.cloudflare.com/

  • 右上の [Sign Up] をクリックして、サインアップ画面に遷移します
  • Email、Passwordを入力して [Create Account] をクリックします
  • workers.dev ドメインのサブドメインのセットアップ画面に遷移すると思うので、お好きなサブドメイン名を入力して、 [Set up] をクリックします。サブドメインは変更できませんがよろしいですか?のポップアップがでるので、 **[Confirm]* をクリックします。
  • プラン選択の画面に遷移すると思うので、Freeプランを選択します。 [Continue with Free] をクリックします
  • 登録時のEメールアドレスにverifyのEメールが届いているので、 [Verify email] をクリックします。
  • 以下のようなWokersのダッシュボードが表示されればOKです。

CLIのインストール

WranglerというCLIをインストールします。

$ npm install -g @cloudflare/wrangler

Wrangler CLI と Cloudflare Account を紐付けます。 Wokers タブの Get your API token をクリックします。 Global API Key という項目があるとおもうので、そこの [View] をクリックし、表示されているAPIキーをコピーします。

Wrangler CLI で Cloudflare Account を認証します。

$ wrangler config
Enter email:
アカウントのEメールアドレス
Enter api key:
先ほどコピーしたAPIキーをペースト
Successfully configured. You can find your configuration file at: /Users/sato.naoya/.wrangler/config/default.toml

CLIでプロジェクトを作成します。以下はGithubのリポジトリからサンプルプロジェクトを作成しています。

$ wrangler generate my-project https://github.com/cloudflare/worker-template
⬇️ Installing cargo-generate...
?  ?  Generating a new webpack worker project with name 'my-project'...
?   Creating project called `my-project`...
✨   Done! New project created /Users/sato.naoya/my-project

Doneとなり、my-projectフォルダが作成されました。

これの他にも、以下のサイトで Cloudflare Workers のサイト上でテンプレートプロジェクトが多数公開されています。

https://developers.cloudflare.com/workers/templates/

作成した Worker プロジェクトをテストしてみます。

$ cd my-project
$ wrangler preview

テスト用のサイトがブラウザで表示され、Hello worker!と表示されています。

プロジェクトをデプロイする

デプロイするには、プロジェクト作成時に作られる wrangler.toml にアカウントIDを設定する必要があります。Workers のダッシュボードにアカウントIDがあるため、それをコピーして以下の account_id に貼り付けます。

account_id = "xxxxxxxxxxxxxxxxx"
name = "my-project"
type = "webpack"
route = ""
workers_dev = true
zone_id = ""

アカウント作成時にセットアップした、workers.devドメインにプロジェクトをデプロイします。コマンド一つでデプロイできます。

$ cd my-project
$ wrangler publish
⬇️ Installing wranglerjs...
⬇️ Installing wasm-pack...
✨  Built successfully, built project size is 535 bytes.
✨  Successfully published your script to https://my-project.xxxxxxxxxx.workers.dev

デプロイできました。URLがあるため、さっそくアクセスしてみます。

$ curl https://my-project.xxxxxx.workers.dev/
Hello worker!

Hello worker! と表示されました。デプロイできているようです。これでCLIのセットアップとJavaScriptを動かすための準備が整いました。

Serverless Functionをデプロイしてみる

Cloudflare Workers を使って、Serverless Functionを作成してみます。公式のチュートリアルで、QRコードを生成する Function を作るチュートリアルがあるため、それをデプロイしてみます。

プロジェクトの作成

まずは、Cloudflare Workers のプロジェクトを作成します。

wrangler generate qr-code-generator
cd qr-code-generator

プロジェクトを作成すると、プロジェクト直下にindex.jsが作成されるので、中身を見てみます。

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})
/**
 * Respond with hello worker text
 * @param {Request} request
 */
async function handleRequest(request) {
  return new Response('Hello worker!', {
    headers: { 'content-type': 'text/plain' },
  })
}

AWS Lambda などと同じようにハンドラ関数を作ってその中に処理を書いていく形です。Cloudflare Workers では、リクエストをfetchイベントで受け取り、ハンドラ関数でレスポンスを返すと言った流れです。下記の構成だと、リクエストを受け取った後、Body にHello workers!という文字列と、Header にContent-Typeをつけてレスポンスを返しています。

POSTの時QRコードをレスポンスとして返す関数を作成する

index.jsを修正して、リクエストが POST の時にレスポンスを返す関数を作成します。request.methodでリクエストされたHTTPメソッドを取得できます。

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

// QRコードを作成する関数を作成
const generate = async request => {
  return new Response('Hello worker!', {status: 200});
};

/**
 * Respond with hello worker text
 * @param {Request} request
 */
async function handleRequest(request) {

  let response;
  // リクエストがPOSTの時だけ、QRコードを作成する関数を呼び出す
  if (request.method == 'POST') {
    response = await generate(request);
  } else {
    response = new Response('Expected POST', { status: 500 });
  }
  return response;
}

Cloudflare Workers では、npm によるパッケージ管理もサポートしています。今回はQRを生成する関数を作成するため、qr-imageライブラリをインストールします。

$ npm install --save qr-image

インストールが終わったため、コードを修正します。

const qr = require('qr-images');

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
});

// QRコードを作成する関数を作成
const generate = async request => {
  const headers = { 'Content-Type': 'image/png' }
  const body = request.json(); // request.json()でリクエストのボディ部をJSON形式で取得します
  const text = body.text; // bodyからQR化するテキストを取得します
  const qr_png = qr.imageSync(text || 'https://workers.dev') // ここでPNG形式のQRコードを作成

  return new Response(qr_png, { headers });
};

GETの時、Webページを返す関数を作成する

上記で作成した、QRを取得する関数をテストするために、POST リクエストを投げるだけのWebページを作成します。

const landing = `
<h1>QR Generator</h1>
<p>Click the below button to generate a new QR code. This will make a request to your serverless function.</p>
<input type="text" id="text" value="https://workers.dev"></input>
<button onclick='generate()'>Generate QR Code</button>
<p>Check the "Network" tab in your browser's developer tools to see the generated QR code.</p>
<script>
  function generate() {
    fetch(window.location.pathname, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text: document.querySelector("#text").value })
    })
  }
</script>
`

/**
 * Respond with hello worker text
 * @param {Request} request
 */
async function handleRequest(request) {
  
  let response;
  // リクエストがPOSTの時は、QRコードを作成する関数を呼び出す
  if (request.method == 'POST') {
    response = await generate(request);
  } else {
    // GETの時は、HTMLをレスポンスとして返す
    response = new Response(landing, { headers: { 'Content-Type': 'text/html' } });
  }
  return response;
}

デプロイする

Cloudflare Workers にデプロイします。

wrangler publish

デプロイが成功すると、Cloudflare Workers のダッシュボードにデプロイしたWorkerが表示されています。

Workerの隣のアイコンをクリックすると、サイトに遷移します。Generate QR CodeをクリックするとQRコードが取得されるはずです。

まとめ

Cloudflare Workers を触ってみました。Serverless Days Tokyo 2019 のセッションでは、静的なWebサイトを Cloudflare Workers でホスティングして、アクセスされた国によってサイトの言語をローカライズするというデモでした。まだ、機能のさわりしか試していないため、色々触ってみたいと思います。また、1日10万リクエストまで無料枠があるため、アカウントさえ作れば気軽に試せますので、興味がある方は試してみてはいかがでしょうか