3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

cloudflare pagesにnext.js & auth.jsの環境を作ってみた

Posted at

この記事はHacobu Advent Calendar 2024の22日目の記事です。

vercelの移行先候補としてよくあがるのが cloudflare pages。

そんなcloudflare pagesにnext.jsauth.jsのスタックで環境を作れないか試してみました。

cloudflare pages & next.jsはすでに詳しく解説されている記事があるので、割愛しつつハマりポイントのみコメントします。ここではauth.js周りの実装例を見ていきたいと思います。

node compatibilityは大事

wranglerの設定ファイルである wrangler.tomlドキュメントを参考に作成します。

#:schema node_modules/wrangler/config-schema.json
name = "my-next-app"
compatibility_date = "2024-12-16"
compatibility_flags = ["nodejs_compat"]
pages_build_output_dir = ".vercel/output/static"

nodeのapiを利用するためworker ランタイムで互換性フラグを有効にします。compatibility_dateは最新のものを選んでください。少し古いものだと、エラーが発生し動かなくなるケースがあります。

wrangler.toml からbindingsや環境変数の設定を読み取って型情報を生成することができます。

pnpm wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts

生成されたものをtsconfig.jsonのincludeに指定することで、CloudflareEnvという型が利用できます。

wrangler.tomlはcommitするので機密情報は別で管理したいです。localで.envのようにsecretを読み込めるようにdatabaseのconnectionやgoogleなどの情報を.dev.varsに登録します。.dev.varsに登録することでwranglerがsecret情報として扱ってくれ型定義にも反映してくれます。

TURSO_URL=""
TURSO_AUTH_TOKEN=""

AUTH_SECRET=""
AUTH_GOOGLE_ID=""
AUTH_GOOGLE_SECRET=""

@cloudflare/next-on-pagesを追加する

素のnext.jsをbuildしたものをcloudflare pagesにdeployするだけではもちろん動きません。cloudflare pageで動くようにbuildしたものを変換する必要があります。また開発時にもwranglerを起動し環境変数やbindingsをlocalで再現する必要があります。

それを実現してくれるツールが@cloudflare/next-on-pagesです。

pnpm i @cloudflare/next-on-pages

開発時にlocalでbindingを読み取れるようにします。

// next.config.ts
import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev';

if (process.env.NODE_ENV === 'development') {
  await setupDevPlatform();
}

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;

package.jsonのscriptにbuildコマンドを追加します

"pages:build": "npx @cloudflare/next-on-pages",

これで pnpm pages:buld でbuildしたものをcloudflare pagesにdeployできるようになりました。

auth.js

基本的にはこちらのドキュメント通りに進めます。

下記コマンドで生成したランダムな文字列はsecretのAUTH_SECRETに指定してください。

pnpm dlx auth secret

auth.jsはデフォルトでsessionをCookieに保存します。なのでデータベースは必要ないのですが、今回はユーザー情報を保存する想定でデータベースを用意します。データベースはlibsqlのturso、ormはdrizzleを利用します。

こちらもドキュメントに詳しいやり方が書いてるのでそれに従って設定します。

google認証をできるようにするため google providerを追加します。

ドキュメント通りに進めると最終的にauth.tsはこのようになります。

// auth.ts
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { db } from "./schema"
 
export const { handlers, auth } = NextAuth({
  adapter: DrizzleAdapter(db),
  providers: [Google],
})

ここまではほぼドキュメント通りに進めるだけです。node runtimeの場合はこれで完了なのですが、cloudflare pagesで動かすためにはもうひと手間加えます。というのも、workerでは process.env から環境変数が取得できません。auth.jsもdrizzleに getRequestContextからenvを取得し明示的に渡してあげる必要があります。

// auth.ts
import {getRequestContext} from '@cloudflare/next-on-pages';
import {drizzle} from 'drizzle-orm/libsql/web';
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { schema } from "./schema"
 
export const { handlers, auth } = NextAuth(() => {
  const {env} = getRequestContext();
  const db = drizzle({url: env.TURSO_URL, authToken: env.TURSO_TOKEN}, schema);
  return {
    secret: env.AUTH_SECRET,
    adapter: DrizzleAdapter(db),
    providers: [
      Google({
        clientId: env.AUTH_GOOGLE_ID,
        clientSecret: env.AUTH_GOOGLE_SECRET,
      }),
    ],
  };
})

最後に edge上で動くのでroute.tsにruntimeの宣言を追加します。

// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"

export const runtime = 'edge';

export const { GET, POST } = handlers

これで動くようになりました🎉

Dec-18-2024 14-43-23.gif

まとめ

簡単そうに見えるのですが、最初に試したときはnode compatibilityに対応していないapiをauth.jsが使っていたりしてエラーになるケースに何度もぶつかりました。またエラーの原因を特定するのも難しく対応されるまで待つ必要がありました。なので、本番環境で安定して動かすには少しハードルが高い気がします。とはいえ、コミュニティは活発なので放置されない安心感はあります。

コストも抑えられCDN上で動くというメリットを考えると、簡単なアプリを作る有力な選択肢にしたいと思いました。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?