💡

cloudflare pages + nextjs

2024/08/28に公開

半年以上前に技術調査しつつメモとして残していた記事を供養する。
特に内容精査もしていないし、何か結論があるわけではないので今もそのまま適用できる保証はありません。

create account

https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/

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

https://github.com/nextauthjs/next-auth-v5-example/blob/main/.env.local.example
ここのenv.local.exampleに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}   

https://developers.cloudflare.com/d1/get-started/

ルートディレクトリに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

https://authjs.dev/reference/adapter/drizzle

adapterのページに書いてある通りにschema.tsを作成する。

drizzle

dbインスタンスを初期化してexportします。

import { drizzle } from "drizzle-orm/d1";

export const db = drizzle(process.env.DB);

https://orm.drizzle.team/docs/get-started-sqlite#cloudflare-d1

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を変更する。
https://developers.cloudflare.com/d1/reference/migrations/#wrangler-customizations

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

https://developers.cloudflare.com/workers/wrangler/configuration/#environmental-variables

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