Open4

ほう・・・Next.jsですか・・・。知らない子ですね。

Nuu氏Nuu氏

この投稿はフィクションです。実在の人物や団体などとは関係ありません。

###あらすじ
当初5人いたプロジェクトは、私がアサインされて2週間しないうちにPM&PLがチームを離れた。さらに程なくしてフロントエンジニアも不慮の神隠しにあい、かつて隆盛を極めたチームの面影はそこにはなく、三十路の男とバックエンドエンジニア(イケメン)の2名を残すのみとなった。

「これは・・・やばいっすね・・・w」とため息交じりに笑うイケメン
その笑顔になぜか照れる三十路の私
微妙な雰囲気になりかけたその刹那、空気を震わせ神は告げた――――
神「明日からNuuさんが画面の方作ってください!PMさんがいけるって言うてました!あとPMもお願いします!」
ワイ「ぱおんぬ」

三十路から始めるNext.js

目的

・Next.js 14.0.1 をキャッチアップしながら実装時のメモなどを投稿する
・最後の仲間がフロントを書くことになった際、実装の補助になるよう

Nuu氏Nuu氏

まずはNext.jsとは

見出し曰く「webアプリケーション用のreact.jsフレームワーク」
フルスタックのwebアプリケーションを作成できるらしい。

フルスタックってどういうこと、私この2週間バックエンドの処理を書いていたんだけど内部でexpressでも使ってるんか?

Next.jsには何が入っているのか

早くwebアプリケーションを作るためのツールだそうです。

・Image,Font,Scriptなどの静的ファイルを最適化するツール(バンドラーとかが含まれている?)

・サーバーからUIを配信するツール
 →(AppRouter, React Suspense フロントのファイル構築とかルーティングとかする機能なのかな?)

・sass, tailwind, styled-jsxが使える
 →(styled-jsxはじめまして。ソース見た感じtailwind使ってる様子)

React server component(RSC)
 →javascriptを送信せずにコンポーネントを追加するReactの機能

上記のURLを読んだ際のメモ。

・server componentはビルド中に実行されるらしい。
 (アプリケーションのビルドなのかHTMLファイルのビルドなのか不明)
・静的ファイルの読み込みやコンテンツのフェッチを事前に行うらしい。
・APIを作成せずにデータにアクセスすることができる。
・server component->client componentへのデータの受け渡しは
 propsを使って可能(実装時に再度確認)
・RSCはNext.js App Routerでリリースされ、機能は密結合(特にバンドラー)
 →使うときはAppRouterと併用するのが無難?
・コンポーネントがデータを読み込み中にSuspenseを使うことで、
 段階的にコンテンツを表示させることができる。読み込み順を制御するのか
スケルトンなど具体的な説明がなくよくわからなかった
 (最後まで読んだところ、2023/3機能実装中とのことでした)
・ 以降は実装予定の構想についてでした。

ドキュメントというかブログ記事でした。最近リリースされた機能らしいので機能調査と並行して実装になるかも・・・

・Route Handlers
→フロントエンドから呼び出せる、サードパーティーアプリへのセキュアな接続を提供するAPIエンドポイントを作る機能?

・データ取得の役割分担はreact側でcomponentを非同期待機し、
 Next.js側でサーバー、クライアントからのデータ取得をサポートする。
 (要件を見てみる限り、この機能を使うシーンがまだ見当たらない・・・
 なんでNext.js使うことになったんだ・・・前任者帰ってきて・・・)
 ここまで読んだ感想は、フロント→バックエンドとの連携が
 いけてないからMPAっぽく実装できる手段もサポートしますって感じなのか

Node.jsランタイムとEdgeランタイム
 ・ランタイムは選べる
  →各ページまたはレイアウトで定義でき、デフォルトはNode.js
 
 ・Node.jsランタイムはNode.jsのAPIとパッケージなどの
  エコシステムを使うことができる
  一方EdgeランタイムはWebAPI準拠のものが使える。
  →なるべくNode.jsでやりましょう

Next.jsのルーティング
 RSC上に構築されたapp Routerがディレクトリ構造から
 URLを作ってくれたり良しなにしてくれるらしい。

現状の理解

Next.jsはバックエンドの処理もシームレスに実装できる様になっているので(以前のバージョンは違ったような?)、一旦フレームワーク内でどこまで実装できるかを見てみる必要がある。なるべくNext.jsのフレームワーク内で完結したい。

すでに一部フロントの開発が実装されているので、実装を確認しながら、適宜学習内容を適用していく。

インストールと起動については公式を参照して問題なく起動した。

Nuu氏Nuu氏

Next.jsのRouterについて

参照ドキュメント
App Router / Page Router

App Router
→RSC、ストリーミングなどReactの最新機能を使えるようにするためのルーター。

Page Router
→Next.jsのオリジナルのルーター。サーバーレンダリングのReactアプリを作れる。

Page Router→ App Routerへの移行はサポートしている。
両Routerの併用、段階的な移行も可能とのこと。
今回のプロジェクトはsrc/appとなっているので
最初からApp Routerが使われている。

POINT
・appディレクトリをroot(/)として、配下のディレクトリ名がURLになる

app
 └item
 | └page.tsx(/item)
 └user
 | └page.tsx(/user)
 └layout.tsx
 └page.tsx(/)

・特定の処理を行うファイルを作成できる。

ファイル名 動作
layout ファイルのあるパスと配下のパスに共有UIとして読み込まれる
page ファイルが存在するとパスとして認識されるようになる。またそのパス独自のUIを定義できる。
layoutの動作

下記の例であれば、/item でレンダリングされるファイルは
app/layout → item/layout → item/page という形になる

app
 └item
 | └page.tsx(/item)
 | └layout.tsx
 └user
 | └page.tsx(/user)
 └layout.tsx
 └page.tsx(/)

ルートグループの作成

:::details
ディレクトリを(ディレクトリ名)にすることで、URLから省略される。

app
 └(admin)    adminはURLパスには含まれない
 | └shop
 | |└page.tsx(/shop)
 | |└layout.tsx
 | └item
 |  └page.tsx(/item)
 |  └layout.tsx
 └user
 | └page.tsx(/user)
 └layout.tsx
 └page.tsx(/)

:::

URLをたたくとページが表示されているので、
ドキュメント通りに動作している。
(Route Group視覚的にわかりやすくていいね!)

次は手つかずの認証系をさわっていく。

Nuu氏Nuu氏

認証系機能を実装する

Next.jsはデフォルトの認証機能を持たないので、App Routerに対応したライブラリを探していく。
ドキュメントには以下の4つが紹介されている。
NextAuth.js
 →それぞれのライブラリ名で検索したところ、NextAuth.jsが一番ヒットしたので、スタンダードなのだろうということで、こちらを詳しく調査
・Clerk
・Auth0
・Stytch

セットアップはこちら

今回はNext.js14でApp Routerを使うので
専用のRoute Handlersの設定方法を実施する

NextAuthにオプションを渡してリクエストを処理する、
NextAuthはGET,POSTのAPIが実装されているのらしい

/app/api/[...nextauth]/route.ts
import { options } from "@/app/options";
import NextAuth from "next-auth";

const handler = NextAuth(options);

export { handler as GET, handler as POST };
NextAuth()について
node_modules/src/next/index.ts
function NextAuth(options: AuthOptions): any

AuthOptions型の引数を渡すらしい↓

node_modules/next-auth/src/core/types.ts
export interface AuthOptions {
  /**
   * An array of authentication providers for signing in
   * (e.g. Google, Facebook, Twitter, GitHub, Email, etc) in any order.
   * This can be one of the built-in providers or an object with a custom provider.
   * * **Default value**: `[]`
   * * **Required**: *Yes*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#providers) | [Providers documentation](https://next-auth.js.org/configuration/providers)
   */
  providers: Provider[]
  /**
   * A random string used to hash tokens, sign cookies and generate cryptographic keys.
   * If not specified, it falls back to `jwt.secret` or `NEXTAUTH_SECRET` from environment variables.
   * Otherwise, it will use a hash of all configuration options, including Client ID / Secrets for entropy.
   *
   * NOTE: The last behavior is extremely volatile, and will throw an error in production.
   * * **Default value**: `string` (SHA hash of the "options" object)
   * * **Required**: No - **but strongly recommended**!
   *
   * [Documentation](https://next-auth.js.org/configuration/options#secret)
   */
  secret?: string
  /**
   * Configure your session settings, such as determining whether to use JWT or a database,
   * setting the idle session expiration duration, or implementing write operation throttling for database usage.
   * * **Default value**: See the documentation page
   * * **Required**: No
   *
   * [Documentation](https://next-auth.js.org/configuration/options#session)
   */
  session?: Partial<SessionOptions>
  /**
   * JSON Web Tokens are enabled by default if you have not specified an adapter.
   * JSON Web Tokens are encrypted (JWE) by default. We recommend you keep this behaviour.
   * * **Default value**: See the documentation page
   * * **Required**: *No*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#jwt)
   */
  jwt?: Partial<JWTOptions>
  /**
   * Specify URLs to be used if you want to create custom sign in, sign out and error pages.
   * Pages specified will override the corresponding built-in page.
   * * **Default value**: `{}`
   * * **Required**: *No*
   * @example
   *
   * ```js
   *   pages: {
   *     signIn: '/auth/signin',
   *     signOut: '/auth/signout',
   *     error: '/auth/error',
   *     verifyRequest: '/auth/verify-request',
   *     newUser: '/auth/new-user'
   *   }
   * ```
   *
   * [Documentation](https://next-auth.js.org/configuration/options#pages) | [Pages documentation](https://next-auth.js.org/configuration/pages)
   */
  pages?: Partial<PagesOptions>
  /**
   * Callbacks are asynchronous functions you can use to control what happens when an action is performed.
   * Callbacks are *extremely powerful*, especially in scenarios involving JSON Web Tokens
   * as they **allow you to implement access controls without a database** and to **integrate with external databases or APIs**.
   * * **Default value**: See the Callbacks documentation
   * * **Required**: *No*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#callbacks) | [Callbacks documentation](https://next-auth.js.org/configuration/callbacks)
   */
  callbacks?: Partial<CallbacksOptions>
  /**
   * Events are asynchronous functions that do not return a response, they are useful for audit logging.
   * You can specify a handler for any of these events below - e.g. for debugging or to create an audit log.
   * The content of the message object varies depending on the flow
   * (e.g. OAuth or Email authentication flow, JWT or database sessions, etc),
   * but typically contains a user object and/or contents of the JSON Web Token
   * and other information relevant to the event.
   * * **Default value**: `{}`
   * * **Required**: *No*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#events) | [Events documentation](https://next-auth.js.org/configuration/events)
   */
  events?: Partial<EventCallbacks>
  /**
   * You can use the adapter option to pass in your database adapter.
   *
   * * **Required**: *No*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#adapter) |
   * [Adapters Overview](https://next-auth.js.org/adapters/overview)
   */
  adapter?: Adapter
  /**
   * Set debug to true to enable debug messages for authentication and database operations.
   * * **Default value**: `false`
   * * **Required**: *No*
   *
   * - ⚠ If you added a custom `logger`, this setting is ignored.
   *
   * [Documentation](https://next-auth.js.org/configuration/options#debug) | [Logger documentation](https://next-auth.js.org/configuration/options#logger)
   */
  debug?: boolean
  /**
   * Override any of the logger levels (`undefined` levels will use the built-in logger),
   * and intercept logs in NextAuth. You can use this option to send NextAuth logs to a third-party logging service.
   * * **Default value**: `console`
   * * **Required**: *No*
   *
   * @example
   *
   * ```js
   * // /pages/api/auth/[...nextauth].js
   * import log from "logging-service"
   * export default NextAuth({
   *   logger: {
   *     error(code, ...message) {
   *       log.error(code, message)
   *     },
   *     warn(code, ...message) {
   *       log.warn(code, message)
   *     },
   *     debug(code, ...message) {
   *       log.debug(code, message)
   *     }
   *   }
   * })
   * ```
   *
   * - ⚠ When set, the `debug` option is ignored
   *
   * [Documentation](https://next-auth.js.org/configuration/options#logger) |
   * [Debug documentation](https://next-auth.js.org/configuration/options#debug)
   */
  logger?: Partial<LoggerInstance>
  /**
   * Changes the theme of pages.
   * Set to `"light"` if you want to force pages to always be light.
   * Set to `"dark"` if you want to force pages to always be dark.
   * Set to `"auto"`, (or leave this option out)if you want the pages to follow the preferred system theme.
   * * **Default value**: `"auto"`
   * * **Required**: *No*
   *
   * [Documentation](https://next-auth.js.org/configuration/options#theme) | [Pages documentation]("https://next-auth.js.org/configuration/pages")
   */
  theme?: Theme
  /**
   * When set to `true` then all cookies set by NextAuth.js will only be accessible from HTTPS URLs.
   * This option defaults to `false` on URLs that start with `http://` (e.g. http://localhost:3000) for developer convenience.
   * You can manually set this option to `false` to disable this security feature and allow cookies
   * to be accessible from non-secured URLs (this is not recommended).
   * * **Default value**: `true` for HTTPS and `false` for HTTP sites
   * * **Required**: No
   *
   * [Documentation](https://next-auth.js.org/configuration/options#usesecurecookies)
   *
   * - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
   * but **may have complex implications** or side effects.
   * You should **try to avoid using advanced options** unless you are very comfortable using them.
   */
  useSecureCookies?: boolean
  /**
   * You can override the default cookie names and options for any of the cookies used by NextAuth.js.
   * You can specify one or more cookies with custom properties,
   * but if you specify custom options for a cookie you must provide all the options for that cookie.
   * If you use this feature, you will likely want to create conditional behavior
   * to support setting different cookies policies in development and production builds,
   * as you will be opting out of the built-in dynamic policy.
   * * **Default value**: `{}`
   * * **Required**: No
   *
   * - ⚠ **This is an advanced option.** Advanced options are passed the same way as basic options,
   * but **may have complex implications** or side effects.
   * You should **try to avoid using advanced options** unless you are very comfortable using them.
   *
   * [Documentation](https://next-auth.js.org/configuration/options#cookies) | [Usage example](https://next-auth.js.org/configuration/options#example)
   */
  cookies?: Partial<CookiesOptions>
}

コメントとドキュメントを読み合わせて
必要な設定を入れていく

続きはまた