cloudflare pages + nextjs
半年以上前に技術調査しつつメモとして残していた記事を供養する。
特に内容精査もしていないし、何か結論があるわけではないので今もそのまま適用できる保証はありません。
create account
create app
npm create cloudflare@latest my-next-app -- --framework=next
deploy
npm run pages:deploy
⚡️ Build log saved to '.vercel/output/static/_worker.js/nop-build-log.json'
⚡️ Generated '.vercel/output/static/_worker.js/index.js'.
⚡️ Build completed in 0.27s
✔ Enter the name of your new project: … {projectName}
✔ Enter the production branch name: … main
✨ Successfully created the '{projectName}' project.
✨ Compiled Worker successfully
✨ Uploading Worker bundle
✨ Uploading _routes.json
✨ Deployment complete! Take a peek over at https://xxxx.{projectName}.pages.dev
下記warinigが出ますが一旦無視して進めます。
▲ [WARNING] The package "node:buffer" wasn't found on the file system but is built into node.
Your Worker may throw errors at runtime unless you enable the "nodejs_compat" compatibility flag.
Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/ for more details. Imported
from:
- _worker.js/index.js
▲ [WARNING] The package "node:async_hooks" wasn't found on the file system but is built into node.
Your Worker may throw errors at runtime unless you enable the "nodejs_compat" compatibility flag.
Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/ for more details. Imported
from:
- _worker.js/index.js
デプロイされたURL(https://xxxx.{projectName}.pages.dev)にアクセスするとエラー画面が出ます。
nodejsの互換性フラグが立っていないと警告され、what can i doセクションで修正の仕方が指示されています。
add nodejs_compat flg
workers & pages > 設定 > 互換性フラグ
プロダクションとプレビューの両方にnodejs_compatフラグを設定します。
再デプロイ
今度はデプロイ時に先ほどのwarningは出ません。
サイトにアクセスしていつものNextjsのサイトが表示されていればOK。
NextAuth
今回利用したバージョンは5.0.0-beta.9です。
npm install next-auth@beta
ERROR
UnknownAction: Cannot parse action at /api/auth/session
AUTH_URLに変なパスを指定すると発生する。
逆に何も指定しなければ問題なく通る。
// OK
AUTH_URL=http://localhost:3000/api/auth
NEXTAUTH_URL=http://localhost:3000/api/auth
// NG
AUTH_URL=http://localhost:3000
NEXTAUTH_URL=http://localhost:3000
AUTH_URL=http://localhost:3000
と書いてあったのでハマってしまった。
TypeError: "ikm"" must be an instance of Uint8Array or a string
secretを設定してないと発生する。
AuthConfig.sessionを手動で設定するか、AUTH_SECRETを環境変数に設定する
NEXTAUTH_URLと違い、NEXTAUTH_SECRETは読み込まれない。
// OK
AUTH_SECRET=secret
// NG
NEXTAUTH_SECRET=secret
GitHub loginで404
// OK
AUTH_GITHUB_ID=aaa
AUTH_GITHUB_SECRET=aaa
// NG
GITHUB_ID=aaa
GITHUB_SECRET=aaa
// NG
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
D1
create D1
npx wrangler d1 create {project_name}
ルートディレクトリにwrangler.tomlを作成し、コンソールに出力された下記の部分をコピペする。
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "{database_name}"
database_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
bindingで定義する名前(process.env.{binding})でD1Databaseインスタンスにアクセスできます。
Auth Adapter
npm install drizzle-orm @auth/drizzle-adapter
npm install drizzle-kit --save-dev
adapterのページに書いてある通りにschema.tsを作成する。
drizzle
dbインスタンスを初期化してexportします。
import { drizzle } from "drizzle-orm/d1";
export const db = drizzle(process.env.DB);
create migration files
import type { Config } from "drizzle-kit";
export default {
schema: "./src/db/schema.ts",
out: "./drizzle",
} satisfies Config;
migrationファイルの出力先をdrizzleフォルダとしたのでwranglerが読み込むmigrations_dirを変更する。
migrations_dir = "drizzle"
package.jsonにgenerateコマンドを足す。
"scripts": {
"generate": "drizzle-kit generate:sqlite"
},
開発環境の環境変数の設定
wranglerは.envファイルは読み込まず、代わりに.dev.varsファイルを読込む。
なので.envと同じ内容を.dev.varsに書き込む
AUTH_URL=http://localhost:3000/api/auth
AUTH_SECRET=aaa
AUTH_GITHUB_ID=aaa
AUTH_GITHUB_SECRET=aaa
migration
--localフラグをつけて開発環境のD1データベースに対してmigrationを実行する。
npx wrangler d1 migrations apply {database_name} --local
プレビューを実行し、サインインする。
npm run pages:preview
Userレコードが増えていることを確認
npx wrangler d1 execute {database_name} --command="select * from user;" --local
next devはポート3000番、プレビューは8878番なので環境変数書き換えたり、GitHubのOAuthAppのCallback URL書き換えたりするの辛すぎる。なんかいい方法ないかね。。。
ここまでできたら本番環境にmigrationを適用します。
先ほどのコマンドから--localを取り除くだけ
npx wrangler d1 migrations apply {database_name}
本番環境の環境変数を設定
環境変数
workers&pages > project > 設定 > 環境変数
D1のバインディング
workers&pages > project > 設定 > functions
Discussion