このガイドでは、フォーム送信を受け取る Worker を、Cloudflare Pages アプリケーションでホストできる Pages Function へリファクタする方法を説明します。Pages Functions は、アプリケーションと同じプロジェクトディレクトリに置けるサーバーレス関数で、Cloudflare Pages と一緒にデプロイされます。専用サーバーを動かさずに、動的な機能を足すサーバーサイドコードを実行できます。Worker を Pages Function にリファクタする理由は、次のいずれかです。
- Pages アプリケーションが依存するサーバーレス関数を管理していて、別サービスとしての Worker を運用せずにロジックを届けたい場合。
- Worker を Pages Functions へ移行し、Pages Functions のルーティングとミドルウェアを使いたい場合。
- fetch ハンドラーを削除し、適切な
OnRequestメソッドに置き換えます。Function に合うメソッドは Functions を参照してください。 - 新しい
OnRequestメソッドにcontextオブジェクトを引数として渡し、コンテキストパラメーターのプロパティ(request、env、params、next)へアクセスします。 - ルートハンドラーの前後で実行する必要があるロジックは、ミドルウェアで扱います。Functions ドキュメントの Middleware の使い方 を参照してください。
リファクタの流れを説明するため、このガイドでは簡単なフォーム送信の例を使います。
フォーム送信は Worker でも扱えます。一方で、フォームは特定のアプリケーションに紐づくことが多いため、Pages Functions の用途にも向きます。
すでに Worker でフォームを扱っている場合、その Worker をデプロイし、HTML フォームの action 属性に URL を追加しているはずです。つまり、送信の扱い方を変えるときは、Worker スクリプトを変更する必要があります。Worker のロジックを複数のアプリケーションで使っている場合、Pages Functions は向きません。
一方、関数ロジックをアプリケーションと同じプロジェクトディレクトリにまとめたいときは、Pages Function が役立ちます。
Pages Functions でアプリケーションを作ると、クライアント側とサーバーレスのロジックを同じ場所で管理でき、コードの記述とデバッグがしやすくなります。
Airtable ↗ は、共同作業向けアプリケーションを作るローコードプラットフォームです。ワークフローのカスタマイズ、共同作業、フォーム送信の処理に使えます。この例では、Airtable のフォーム送信機能を使います。
Airtable ↗ は、同じアカウントの複数テーブルに情報を保存できます。送信ロジック用の Worker を作る最初の手順は、Wrangler で、特定フォルダー内またはアプリケーションのルートに新しい Worker を初期化することです。
この手順で、Airtable 送信用 Worker を書くためのボイラープレートができます。Worker を書いたら、デプロイ向けにプロジェクトを設定 したあと、Cloudflare のグローバルネットワークへデプロイできます。Workers でフォーム送信を扱う完全なチュートリアルは、Airtable でフォーム送信を扱う を参照してください。
次のコードブロックは、Airtable のフォーム送信を扱う Worker の例です。
Worker のパス名が /submit のとき、非同期関数 submitHandler が呼ばれます。この関数はリクエストメソッドが POST であることを確認し、フォーム入力を解析して、認証情報を使って Airtable へ投稿します。認証情報は Wrangler secret で保存できます。
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === "/submit") {
return submitHandler(request, env);
}
return fetch(request.url);
},
};
async function submitHandler(request, env) {
if (request.method !== "POST") {
return new Response("Method not allowed", {
status: 405,
});
}
const body = await request.formData();
const { first_name, last_name, email, phone, subject, message } =
Object.fromEntries(body);
const reqBody = {
fields: {
"First Name": first_name,
"Last Name": last_name,
Email: email,
"Phone number": phone,
Subject: subject,
Message: message,
},
};
return HandleAirtableData(reqBody, env);
}
const HandleAirtableData = (body, env) => {
return fetch(
`https://api.airtable.com/v0/${env.AIRTABLE_BASE_ID}/${encodeURIComponent(
env.AIRTABLE_TABLE_NAME,
)}`,
{
method: "POST",
body: JSON.stringify(body),
headers: {
Authorization: `Bearer ${env.AIRTABLE_API_KEY}`,
"Content-type": `application/json`,
},
},
);
};上の Worker をリファクタするには、Pages プロジェクトディレクトリへ移動し、/functions フォルダーを作成します。/functions に form.js ファイルを作成します。このファイルがフォーム送信を扱います。
次に、form.js で単一の onRequestPost をエクスポートします。
export async function onRequestPost(context) {
return await submitHandler(context);
}すべての Worker には fetch イベントを待つ addEventListener がありますが、Pages Function では不要です。代わりに単一の onRequest 関数を export し、扱う HTTPS リクエストに応じて名前を付けます。関数に合うメソッドは Function のドキュメント を参照してください。
上のコードは request と env を引数に取り、これらのプロパティを 元の Worker から変更していない submitHandler 関数へ渡します。ただし、Functions では HTTPS リクエストの種類を指定できるため、Worker 内の request.method チェックは削除できます。これは、onRequest ハンドラーの名前付けで Pages Functions が扱います。
次に、submitHandler 関数を導入し、env パラメーターをプロパティとして渡します。これにより、下の HandleAirtableData 関数で env にアクセスできます。この関数は、Airtable の認証情報を使って Airtable へ POST リクエストを送ります。
export async function onRequestPost(context) {
return await submitHandler(context);
}
async function submitHandler(context) {
const body = await context.request.formData();
const { first_name, last_name, email, phone, subject, message } =
Object.fromEntries(body);
const reqBody = {
fields: {
"First Name": first_name,
"Last Name": last_name,
Email: email,
"Phone number": phone,
Subject: subject,
Message: message,
},
};
return HandleAirtableData({ body: reqBody, env: env });
}最後に、HandleAirtableData 関数を作成します。この関数は、Airtable の認証情報とリクエスト本文を使って Airtable へ fetch リクエストを送ります。
// ..
const HandleAirtableData = async function onRequest({ body, env }) {
return fetch(
`https://api.airtable.com/v0/${env.AIRTABLE_BASE_ID}/${encodeURIComponent(
env.AIRTABLE_TABLE_NAME,
)}`,
{
method: "POST",
body: JSON.stringify(body),
headers: {
Authorization: `Bearer ${env.AIRTABLE_API_KEY}`,
"Content-type": `application/json`,
},
},
);
};Function は Wrangler でローカルテスト できます。このガイドを完了すると、フォーム送信用 Worker をフォーム送信用 Pages Function へリファクタできています。