どうせみんな、Cloudflareのことが好きなんでしょ。
私も大好き。
だってCloudflareってDBとかストレージとか色々あって、そんでもって無料枠が東京ドーム◯個分だもんね。
もうできるだけCloudflareに乗っかってアプリ作りたいわよね。
だから私、やってみたわ。
やってみた感想は、辛かったわ。。。
だけどその辛さを超えてしまえば、まぁ動くようになったしええか、って感じだわ。
何が辛くて、どうやって辛さを解消したかをシェアするわね。
Cloudflareざんまいの構成
- Cloudflare D1
- Cloudflare R2
- Cloudflare Workers
- Cloudflare Workers KV
- Cloudflare Images
- Cloudflare Registrar
- Next.js
- Auth.js
- Drizzle ORM
すんごいCloudflareでまとまっててsimpleな構成よね。
この構成でローカルで開発してて全てがうまくいって、「アタシ最強!」ってなってたわ。
だけどCloudflare Workersにデプロイしたら全然うまくいかなくなって、「アタシ最弱…」ってなったわ。
このとき思ったわ。
「simpleだけどeasyじゃない」って。
非easyポイント
Next.jsとCloudflareの組み合わせだから沼った内容とか、Next.js & Vercelの感覚で使ったら沼った内容を取り上げるわ。
- 最新のNext.jsが使えない
- Prismaが使えない
- サインアウトができない
- generateStaticParamsが使えない
- R2にアップロードできない
最新のNext.jsが使えない
これを書いている2025年7月下旬時点でNext.jsはv15.4がリリースされてるけど、v15.4はCloudflare Workersでは使えないわ。
Cloudflare Workersにデプロイは成功するんだけど、アクセスしてみるとたしか500エラーの画面になったわ。
ログには以下が出てたわ。
Failed to prepare server Error: An error occurred while loading the instrumentation hook
解決策
Next.jsをv15.3にしたらエラーを解決できて、無事に動いたわ。
v15.4が使えない問題は、おいおい対応してもらえるかも。
ありがとがんば٩(๑•o•๑)و ファイト♡♡
Prismaが使えない
Drizzleを使う前にPrismaを使ってて、ローカルではめっちゃ元気に動いてたのよ。
でもCloudflare Workers上でDBにデータを保存しようとしたら、500エラーになったわ。
ログには、Error: [unenv] fs.readdir is not implemented yet!
ってエラーが出てたわ。
解決策
「Drizzleオススメ」ってコメントを見かけたからPrismaをDrizzleに差し替えたら、Cloudflare Workers上でも元気よく動いてくれたわ。
ただ、Drizzleに差し替えた後に分かったんだけど、私がPrisma Clientの出力先を設定しちゃったのが、エラーの原因だったっぽいわ。
OpenNextのドキュメントに、「出力先を書かんでよろし」って書いてあるのを見つけたの。
だからPrisma Clientの出力先を変えなくていいんだったら、Prismaを使えるわよたぶん。
サインアウトができない
Auth.jsって、サーバーサイド用とクライアント用のsignOut
があるじゃない?
import NextAuth from "next-auth";
export const { handlers, signIn, signOut, auth } = NextAuth({
...
import { signOut } from "next-auth/react";
...
この子たちCloudflare Workers上では、どっちを使ってもサインアウト状態にならなかったわ。
私auth()
の戻り値を使ってサインイン状態の判定をしてたんだけど、Cloudflare Workers上では以下の状態になってたわ。
-
signOut
実行 -
auth()
の戻り値がnullになってサインアウト状態になる - ページをリロードするとサインイン状態になる
ブラウザのデベロッパーツールでCookieを確認したら、サインアウトしても__Secure-authjs.session-token
が消えなかったから、サインイン状態に戻っちゃってたのね。
解決策
middlewareでCookieを削除するようにしたら、サインアウト状態になったわ。
上記のIssueに__Secure-authjs.session-token
が消えなかったか理由が書いてあったわ。
サインアウトした際に2種のSet-Cookieが送信されてるみたいで、その2種を読む順番がCloudflare Workersと噛み合ってなかったみたい。
これはAuth.jsとCloudflare Workersの相性がよろしくなかったのね。
だからCloudflare Workersを使うのなら、Auth.js以外を使ってみるといいわ。
最近はBetter Authっていう子を、界隈でよく見かけるわね。
generateStaticParamsが使えない
こういうの書くでしょ。
export async function generateStaticParams() {
const { env } = getCloudflareContext()
const db = drizzle(env.DB, { schema })
...
そしてビルドしたら、以下のエラーが出たわ。
ERROR: `getCloudflareContext` has been called in sync mode in either a static route or at the top level of a non-static one, both cases are not allowed but can be solved by either:
- make sure that the call is not at the top level and that the route is not static
- call `getCloudflareContext({async: true})` to use the `async` mode
- avoid calling `getCloudflareContext` in the route
ちなみにsitemap.tsでもDBを使う状態でビルドしたら、同じエラーが起きたわ。
解決策
エラーメッセージに書かれてる、非同期モードを使うことで解決できたわ。
export async function generateStaticParams() {
const { env } = await getCloudflareContext({ async: true })
const db = drizzle(env.DB, { schema })
...
ただ、私drizzle
関数の戻り値を返すユーティリティを各所で使っていたから、色々と書きなおすのがめんどくさかったわ。
最初から言ってくれればよかったのに。
R2にアップロードできない
以下のドキュメントに従って、ファイルのアップロード機能を実装したわ。
そしてCloudflare Workers上でファイルをアップロードしたら、以下のエラーが出たわ。
Error: [unenv] fs.readFile is not implemented yet!
解決策
@aws-sdk/client-s3
の代わりにaws4fetch
を使うことで、Cloudflare Workers上でファイルをアップロードできるようになったわ。@aws-sdk/client-s3
が内部でfs
を使ってるのかもね。
このエラーの原因が@aws-sdk/client-s3
を使ってることなんだとしたら、Cloudflare Workersで機能しないライブラリをR2のドキュメントに載せるのはこれいかに、って感じだわ。
ひょっとしたら、simpleじゃない & easyじゃない
アプリを作るために異なる会社のサービスを組み合わせるのって、なんかsimpleじゃないでしょ。
対してCloudflareざんまいって、すごいsimpleよね。
Cloudflareのコンソールに行けば、大抵のことを設定したり確認できるし。
個人的には「なんかまとまってていい!」っていう、精神的な充足感を得られているわ。
とはいえ、実装の観点だとsimpleじゃない気がするわ。
私が沼でもがいた結果、以下の約束事を見つけられたわ。
- Cloudflare Workers & Next.jsを使う場合、特定のバージョンを避ける
- Next.js & Cloudflare D1 & Prismaを使う場合、Prisma Clientの出力先を変更しない
- Cloudflare Workersを使う場合、内部でNode.jsの組み込みモジュールを使っていないライブラリを選定する
- Cloudflare Workers & Auth.jsを使う場合、サインアウトに関する処理をmiddlewareに施す
こういう「コレをするなら、アレをしなければいけない」みたいな約束事があるような状態って、simpleとは言いにくいんじゃないかしら。
だって「Cloudflare WorkersでNext.js使えるよ!」って言われて、いざ手を出したら「あ、ただしバージョンは15.3にしなきゃ動かないよ」って言われたら、「えーなにそれ聞いてない」ってなるじゃないのさ。
加えて、こういう約束事が書かれている場所がGitHubのIssueであったり、ドキュメントだったりに点在しているところも、simpleではない印象だわ。
例えばPrisma Clientの出力先を変えると機能しなくなる旨は、OpenNextのドキュメントには書いてあるけど、Cloudflare D1とPrismaのドキュメントには書かれていないっぽいわ。
これに関してはNext.jsと組み合わせた場合の約束事だから、OpenNextのドキュメントにだけ書いてあるんでしょうけれども。
けど、まぁ、いいわ。
だって、エラーを解決できたもん。
エラーを解決できて、Cloudflareざんまいなsimpleな構成で、アプリを運用できているもん。
「エラー上等!ランニングコスト掛けたくない!」って人なら、Next.js & Cloudflareざんまいにする価値はあるわ。
ちなみにデプロイ先をCloudflare WorkersからVercelに変えれば、前述したeasyじゃないポイントはほぼ解消できると思うわ。
VercelはCloudflare Workersに比べて無料枠が小っちゃいし、無料プランだと商用利用ができないんだけど、そこを許容できるんだったらVercelを使うのもアリよ。
Views: 0