【第29回】いま使っているブログと同じ土俵に立つ|Cloudflare Workers(嫁子が教えるTS講座)

今回のゴール

ここから第6部(応用)です。前回まで(第5部)でNext.jsのアプリを公開できるようになりました。全体の流れは講座の目次へ。


嫁子: 第6部は、このブログ自身の話だよ。

第28回でちらっと言ったけど、「夫のひきだし」はNext.jsじゃなくてCloudflareに置いてあるの。同じことを別の場所でやるとどう違うのかを、最後の3回で見ていくよ。


1. Workersは「関数を世界中に置く」場所

まず、これまでとの違いから。

第28回で公開したNext.jsのアプリは、アクセスが来るとサーバー側でページを組み立てて返していました。Workersも似たことをしますが、置き方の考え方が違います。

これまで(Next.js中心) Workers
動かすもの アプリ全体 リクエストに応える関数1つ
動く場所 指定した地域のサーバー 世界中の拠点(利用者に近い場所)
起動 サーバーが待機している 来たときに起動して、終わったら消える

「サーバーを立てる」のではなく「関数を置いておく」と考えると近いです。誰も来なければ何も動かないので、待機のための費用がかかりません。


2. 作って動かす

手を動かしたほうが早いので、先に作ります。

npm create cloudflare@latest my-worker

いくつか質問されます(何を作るか、言語は何か)。「Hello World」と「TypeScript」を選んでください。

できたフォルダに入って起動します。

cd my-worker
npm run dev

http://localhost:8787/ を開くと Hello World! と表示されます。ここまでアカウント登録は要りません。手元だけで動きます。

嫁子: ここ、地味に大きいところだよ。

第28回のVercelは公開するのに登録が必要だったでしょ。Workersは登録なしで「どんなものか」を確かめられるの。試すだけなら無料も何も関係ない、というのは始めやすさとして効くよ。


3. 中身はこれだけ

生成された src/index.ts を見ると、驚くほど短いです。

export default {
    async fetch(request, env, ctx): Promise<Response> {
        return new Response("Hello World!");
    },
} satisfies ExportedHandler<Env>;

読み方はこうです。

第24回で書いたRoute Handlerと、形がよく似ています。あちらも request を受け取って Response を返していました。実は同じ発想で、Workersのほうがより素の形に近いだけです。

少し足してみる

パスで分岐させると、APIらしくなります。

export default {
    async fetch(request, env, ctx): Promise<Response> {
        const url = new URL(request.url);

        if (url.pathname === "/api/hello") {
            return Response.json({ message: "こんにちは", at: new Date().toISOString() });
        }

        return new Response("Hello World!");
    },
} satisfies ExportedHandler<Env>;

保存して http://localhost:8787/api/hello を開くと、JSONが返ります。

{"message":"こんにちは","at":"2026-09-11T01:22:19.157Z"}

第24回の Response.json() がそのまま使えます。Next.jsで覚えた書き方が、ここでも通用します。


4. 設定ファイルは1つだけ

wrangler.jsonc が設定ファイルです。最初はこれだけしか書いてありません。

{
    "name": "my-worker",
    "main": "src/index.ts",
    "compatibility_date": "2026-09-11",
    "observability": {
        "enabled": true
    }
}
項目 意味
name 公開したときのURLに使われる名前
main 入口のファイル
compatibility_date どの時点の動作に合わせるか
observability ログを記録するかどうか

3つ目が独特なので補足します。Workersの土台は更新され続けますが、この日付を書いておくと、その時点の挙動が保たれます。日付を上げない限り、勝手に動きが変わらない仕組みです。

嫁子: これ、第18回や第22回で言った「世代が違うと動かない」問題への、プラットフォーム側の答えだと思う。

「いつの時点の仕様で動かすか」をこっちが指定できるの。放っておいても壊れないけど、新しい機能が欲しければ自分で日付を上げる。責任の分け方がはっきりしてるよね。


5. 公開するとき

公開はコマンド1つです。

npm run deploy

ここで初めてCloudflareのアカウントが必要になり、ブラウザでのログインを求められます。終わると 〜.workers.dev という形のURLが発行されます。

動かす前に無料の範囲を確認しておいてください。無料枠の内容は変わることがあるので、Cloudflareの公式ドキュメントで今の条件を見るのが確実です。


6. Next.jsとの使い分け

ここが今回いちばん実用的なところです。

向いていること どちらか
画面のあるアプリ(フォーム、一覧、ログイン) Next.js
小さな処理(受け取って、判定して、返す) Workers
既存サイトに機能を1つ足す Workers
静的なサイトの配信 どちらでも可

「画面を作るか、処理を置くか」で分かれます。

このブログのように、記事のファイルからHTMLを組み立てて置いてあるだけのサイトなら、そもそもアプリの枠組みは要りません。そこに診断ツールを1つ足したい、といった場面がWorkersの出番です。

嫁子: 全部をNext.jsで作り直す必要はないの。ここは言っておきたかったところ。

今動いてるものは動かしたまま、足したい機能だけ別に置く。そのほうが壊れる範囲が小さいでしょ。第31回で実際にやるからね。


つまずきポイント

ポートは8787です。第18回のNext.jsが3000番だったので、混同しやすいところです。

Windowsで npx が止まるときは npx.cmd。第15回と同じです。

設定ファイルは wrangler.jsonc です。古い記事では wrangler.toml という別形式で説明されていることがあります。中身は同じものなので、書式が違うだけだと思ってください。


今回のまとめ


次にやること

次回はD1(データベース)を使う回です。第26回のPrismaでやったことを、Cloudflare側の仕組みでやります。

今回の宿題:/api/hello を作って、ブラウザで開いてみてください。JSONが返ってくるところまでが確認できれば十分です。登録は要りません。

嫁子: 第5部までと比べると、だいぶ身軽に感じると思うよ。

ファイル3つで動くからね。小さいものを作るなら、小さい道具のほうが速い。これは第6部を通しての話だよ。