😭

SupabaseがApp Routerに対応しているのを今更知ったので試してみた

2024/01/28に公開

イントロ

SupabaseがApp Routerに対応してるのを今更知りました。
以下の記事は2023-08-10のものなので、かなり長い間、無駄なことをしてました。

https://supabase.com/blog/using-supabase-with-vercel

ということで、今日は、App Routerに対応した(していた)SupabaseでのAuth系の実装方法を試してみようと思います。

We generally recommend using the new @supabase/ssr package instead of auth-helpers. @supabase/ssr takes the core concepts of the Auth Helpers package and makes them available to any server framework.

https://supabase.com/docs/guides/auth/auth-helpers/nextjs

とのことなので、@supabase/ssrを使って実装していこうと思います。

本題

環境構築

リポジトリの作成

ハリボテTODOアプリをテンプレートとしてリポジトリを作成します。

https://github.com/shinaps/nextjs-haribote-todo-app

できました。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp

作成したリポジトリをクローン

git clone git@github.com:shinaps/nextjs-approuter-supabase-todoapp.git
Cloning into 'nextjs-approuter-supabase-todoapp'...
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 44 (delta 0), reused 42 (delta 0), pack-reused 0
Receiving objects: 100% (44/44), 71.36 KiB | 445.00 KiB/s, done.

ハリボテTODOアプリ起動

npm install
npm run dev

Supabaseでプロジェクトを作成

https://supabase.com/dashboard/new

実装

以下のページを参考に実装していきます。

https://supabase.com/docs/guides/auth/server-side/nextjs

パッケージのインストール

npm install @supabase/ssr

環境変数の設定

https://supabase.com/dashboard/project/{Reference ID}/settings/api のURLにアクセスしてProject URLとProject API keysのanon key.env.localに転記します。

.env.local
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key

以下の手順は今回はスキップ可能です。スキップする場合はcreateBrowserClient<Database>createBrowserClientのように書き換えて使用してください。

Supabaseの型情報をクライアントで使用できるようにする(オプショナル)

Supabaseの型情報を生成

https://supabase.com/docs/reference/cli/supabase-gen-types-typescript

https://supabase.com/docs/reference/javascript/typescript-support#generating-typescript-types

npm install supabase
npx supabase login
supabase init
supabase link --project-ref {Reference ID}
supabase gen types typescript --linked > supabase/database.types.ts

これでsupabase/database.types.ts に型の情報が生成されます。

supabase link --project-ref {Reference ID} の時にDBのパスワードが求められるので、忘れてしまった場合は以下のボタンをクリックすればリセットできます。

https://supabase.com/dashboard/project/{Reference ID}/settings/databaseのURLからページにアクセスできます。

clientに型情報を追加

以下のようにジェネリック型にDatabaseという型を渡すことで、データベースの型を参照できるようになります。

import { createBrowserClient } from "@supabase/ssr";
import { Database } from "../../../supabase/database.types";

export const createClient = () => {
  return createBrowserClient<Database>(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
  );
};

クライアントの作成

今回は1種類(Server ActionsとRoute Handlersで使用するクライアント)しか作成する必要はありませんが、実際にアプリケーションで使用する場合は、3種類作成することになると思います。その3種類というのは以下の3つです。

  • Client Componentsで使用するクライアント
  • Server Componentsで使用するクライアント
  • Server ActionsとRoute Handlersで使用するクライアント

サーバーサイドで使用するクライアントが2種類あるのは以下のように、Server ComponentsではCookieの書き込みができないという特徴があるからです。

Cookieの読み取り Cookieの書き込み
Server Components できる できない
Route Handlers できる できる
Server Actions できる できる

Server ActionsとRoute Handlersで使用するクライアントにはcookie-writable-server-client.ts という名前をつけましたが、他にいい名前があればそれを使用してください。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp/blob/main/src/clients/supabase/cookie-writable-server-client.ts

ミドルウェアの作成

ミドルウェアでは Cookieの情報を使用してuserの情報を取得し、userが取得できない場合はサインインのページにリダイレクトする処理になっています。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp/blob/main/src/middleware.ts

プロバイダーの設定

今回はメールアドレスの検証の実装は行わないので、

https://supabase.com/dashboard/project/{Reference ID}/auth/providers のURLにアクセスし、Auth Providers > Email > Confirm emailをOFFにします。

Confirm emailONになっている場合、メールアドレスの確認が完了していないユーザーはサインアップできていてもNULLになるので気をつけてください。

サインイン用のactionを作成

自分はわかりやすいのでsrc/app/services/auth/sign-in.action.ts という名前にして関数名にもActionをつけてますが、actionを付けないといけないという決まりはありません。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp/blob/main/src/app/services/auth/sign-in.action.ts

サインアップ用のactionを作成

サインイン用のactionとほぼ同じです。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp/blob/main/src/app/services/auth/sign-up.action.ts

サインイン用のページを作成

プログレッシブエンハンスメントは捨てました。use clientを使います。

https://github.com/shinaps/nextjs-approuter-supabase-todoapp/blob/main/src/app/sign-in/page.tsx

ここは以下のページを見ていただければわかると思うので、説明は省きます。

わからなかったらコメントかDMしてください。

https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations#forms

終わり・感想

サーバーサイドでのセッションの管理や検証が簡単に実装できるようになっててすごく便利です!

https://supabase.com/docs/guides/auth/server-side/nextjs

こちらのページでもサンプルコードや解説が充実しててわかりやすかったです。

shinaps テックブログ

Discussion