Slide 1

Slide 1 text

T3 Stack 応用編: Next Auth & SSRの実装紹介 Press Space for next page

Slide 2

Slide 2 text

自己紹介 📝 飯野陽平(wheatandcat) 🏢 法人設立(合同会社UNICORN 代表社員) 💻 Work: シェアフル株式会社CTO 📚 Blog: https://www.wheatandcat.me/ 🛠 今までに作ったもの memoir ペペロミア MarkyLinky

Slide 3

Slide 3 text

T3 Stackとは? 最近、話題の Web アプリ開発のアーキテクチャ 以下の 3 つの思想に集点を当てて設計された技術スタック simplicity(簡潔さ) modularity(モジュール性) full-stack typesafety(フルスタックの型安全) t3-appとしてコマンドラインツールも公開されている 全体の紹介は以前スライドを作成したので、そちらを参照 T3 Stack + Supabaseでアプリを作ってみる - Speaker Deck このスライドでは、T3 Stackの応用編として、Next AuthとSSR対応を紹介

Slide 4

Slide 4 text

Next Authとは? Next.jsアプリケーション専用に設計されたオープンソースの認証ライブラリ SSRや、React Server Components等のサーバーサイドでも認証が可能 様々な認証プロバイダーをサポート(Google、Facebookなど) 簡単な設定で認証が実装可能

Slide 5

Slide 5 text

Next Authで認証を実装 Google | NextAuth.js 各プロバイダーの設定は以下のように行う export const authOptions: NextAuthOptions = { providers: [ DiscordProvider({ clientId: env.DISCORD_CLIENT_ID, clientSecret: env.DISCORD_CLIENT_SECRET, }), AppleProvider({ clientId: env.APPLE_ID, clientSecret: env.APPLE_SECRET, }), GoogleProvider({ clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, }), ],

Slide 6

Slide 6 text

Next Authで認証を実装 Google | NextAuth.js 各プロバイダーの設定は以下のように行う DiscordProvider({ clientId: env.DISCORD_CLIENT_ID, clientSecret: env.DISCORD_CLIENT_SECRET, }), export const authOptions: NextAuthOptions = { providers: [ AppleProvider({ clientId: env.APPLE_ID, clientSecret: env.APPLE_SECRET, }), GoogleProvider({ clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, }), ],

Slide 7

Slide 7 text

Next Authで認証を実装 Google | NextAuth.js 各プロバイダーの設定は以下のように行う AppleProvider({ clientId: env.APPLE_ID, clientSecret: env.APPLE_SECRET, }), export const authOptions: NextAuthOptions = { providers: [ DiscordProvider({ clientId: env.DISCORD_CLIENT_ID, clientSecret: env.DISCORD_CLIENT_SECRET, }), GoogleProvider({ clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, }), ],

Slide 8

Slide 8 text

Next Authで認証を実装 Google | NextAuth.js 各プロバイダーの設定は以下のように行う export const authOptions: NextAuthOptions = { providers: [ DiscordProvider({ clientId: env.DISCORD_CLIENT_ID, clientSecret: env.DISCORD_CLIENT_SECRET, }), AppleProvider({ clientId: env.APPLE_ID, clientSecret: env.APPLE_SECRET, }), GoogleProvider({ clientId: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, }), ],

Slide 9

Slide 9 text

ログイン画面の実装 プロバイダーの設定が完了したら、signInのメソッドをコールするだけで以下の画面 import { signIn, signOut, useSession } from "next-auth/react"; signIn("credentials", {callbackUrl: "/",})}> ログイン

Slide 10

Slide 10 text

ログイン画面のカスタマイズ ログイン画面をカスタマイズしたい場合は以下を追加することで可能 export const authOptions: NextAuthOptions = { pages: { signIn: "/auth/signin", error: "/auth/signin", },

Slide 11

Slide 11 text

認証実装①(クライアントサイドで取得) 認証したユーザーの値は以下で取得可能 import { signIn } from "next-auth/react"; function Home() { const { data: session } = useSession(); if (!session) { return (
ログイン前です
) } return (
ログイン後です
{session.user.id}
{session.user.name}
{session.user.email}
) }

Slide 12

Slide 12 text

認証実装①(クライアントサイドで取得) 認証したユーザーの値は以下で取得可能 import { signIn } from "next-auth/react"; const { data: session } = useSession(); function Home() { if (!session) { return (
ログイン前です
) } return (
ログイン後です
{session.user.id}
{session.user.name}
{session.user.email}
) }

Slide 13

Slide 13 text

認証実装①(クライアントサイドで取得) 認証したユーザーの値は以下で取得可能 if (!session) { return (
ログイン前です
) } import { signIn } from "next-auth/react"; function Home() { const { data: session } = useSession(); return (
ログイン後です
{session.user.id}
{session.user.name}
{session.user.email}
) }

Slide 14

Slide 14 text

認証実装①(クライアントサイドで取得) 認証したユーザーの値は以下で取得可能
ログイン後です
{session.user.id}
{session.user.name}
{session.user.email}
import { signIn } from "next-auth/react"; function Home() { const { data: session } = useSession(); if (!session) { return (
ログイン前です
) } return (
) }

Slide 15

Slide 15 text

認証実装①(クライアントサイドで取得) 認証したユーザーの値は以下で取得可能 import { signIn } from "next-auth/react"; function Home() { const { data: session } = useSession(); if (!session) { return (
ログイン前です
) } return (
ログイン後です
{session.user.id}
{session.user.name}
{session.user.email}
) }

Slide 16

Slide 16 text

認証実装②(SSRで認証) SSRで認証したい場合は以下のように実装 import { signIn } from "next-auth/react"; import { type GetServerSideProps } from "next"; import { getServerAuthSession } from "~/server/auth"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); return { props: { session }, }; }; function Home() { const { data: session } = useSession();

Slide 17

Slide 17 text

認証実装②(SSRで認証) SSRで認証したい場合は以下のように実装 export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); return { props: { session }, }; }; import { signIn } from "next-auth/react"; import { type GetServerSideProps } from "next"; import { getServerAuthSession } from "~/server/auth"; function Home() { const { data: session } = useSession();

Slide 18

Slide 18 text

認証実装②(SSRで認証) SSRで認証したい場合は以下のように実装 const { data: session } = useSession(); import { signIn } from "next-auth/react"; import { type GetServerSideProps } from "next"; import { getServerAuthSession } from "~/server/auth"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); return { props: { session }, }; }; function Home() {

Slide 19

Slide 19 text

認証実装②(SSRで認証) SSRで認証したい場合は以下のように実装 import { signIn } from "next-auth/react"; import { type GetServerSideProps } from "next"; import { getServerAuthSession } from "~/server/auth"; export const getServerSideProps: GetServerSideProps = async (ctx) => { const session = await getServerAuthSession(ctx); return { props: { session }, }; }; function Home() { const { data: session } = useSession();

Slide 20

Slide 20 text

認証実装③(RSCで認証) RSCで認証したい場合は以下のように実装 現状はこれが最速の認証方法 import { getServerSession } from "next-auth/next" import { authOptions } from "~/server/auth"; export default async function Home() { const session = await getServerSession(authOptions)

Slide 21

Slide 21 text

認証実装③(RSCで認証) RSCで認証したい場合は以下のように実装 現状はこれが最速の認証方法 export default async function Home() { const session = await getServerSession(authOptions) import { getServerSession } from "next-auth/next" import { authOptions } from "~/server/auth";

Slide 22

Slide 22 text

認証実装③(RSCで認証) RSCで認証したい場合は以下のように実装 現状はこれが最速の認証方法 import { getServerSession } from "next-auth/next" import { authOptions } from "~/server/auth"; export default async function Home() { const session = await getServerSession(authOptions)

Slide 23

Slide 23 text

tRPCでSSRを実装① T3 StackではtRPCでデータ取得を行っている SSRに対応するには、以下のoptionをtrueにするだけでOK 👌 import { createTRPCNext } from "@trpc/next"; export const api = createTRPCNext({ /** * Whether tRPC should await queries when server rendering pages. * * @see https://trpc.io/docs/nextjs#ssr-boolean-default-false */ ssr: true,

Slide 24

Slide 24 text

tRPCでSSRを実装① T3 StackではtRPCでデータ取得を行っている SSRに対応するには、以下のoptionをtrueにするだけでOK 👌 ssr: true, import { createTRPCNext } from "@trpc/next"; export const api = createTRPCNext({ /** * Whether tRPC should await queries when server rendering pages. * * @see https://trpc.io/docs/nextjs#ssr-boolean-default-false */

Slide 25

Slide 25 text

tRPCでSSRを実装② Server-Side Rendering | tRPC ssr:trueにするとtRPCでアクセスしている箇所をサーバーサイドでprefetchする挙動になる 以下のようなコードを実行した場合、クライアントサイドではキャッシュから取得するの動作になる function Schedule() { const router = useRouter(); const { id } = router.query; const schedules = api.schedule.fetch.useQuery({ urlId: String(id) });

Slide 26

Slide 26 text

tRPCでSSRを実装② Server-Side Rendering | tRPC ssr:trueにするとtRPCでアクセスしている箇所をサーバーサイドでprefetchする挙動になる 以下のようなコードを実行した場合、クライアントサイドではキャッシュから取得するの動作になる const schedules = api.schedule.fetch.useQuery({ urlId: String(id) }); function Schedule() { const router = useRouter(); const { id } = router.query;

Slide 27

Slide 27 text

tRPCでSSRを実装② Server-Side Rendering | tRPC ssr:trueにするとtRPCでアクセスしている箇所をサーバーサイドでprefetchする挙動になる 以下のようなコードを実行した場合、クライアントサイドではキャッシュから取得するの動作になる function Schedule() { const router = useRouter(); const { id } = router.query; const schedules = api.schedule.fetch.useQuery({ urlId: String(id) });

Slide 28

Slide 28 text

補足: スライドで参照している開発物の紹介 Repository OOMAKA サービスURL OOMAKA | 年間スケジュール、まとめるなら SSRしている画面を軽くDEMO

Slide 29

Slide 29 text

まとめ T3 Stackを使うとSSR周りは、かなり楽 getServerSidePropsでゴニョゴニョする必要がなくなって開発が捗る Next Authは現状はNext.js専用だが、今後のロードマップで名前をAuthに変更して別フレームワークでも使 用可能になる予定

Slide 30

Slide 30 text

ご清聴ありがとうございました 🎉