【今さら聞けない?!】T3 Stack によるフルスタックWebアプリ開発

# はじめに

今フロントエンド/バックエンドの垣根を超えて巷を賑わせている T3 Stack について調べてみました。要素技術一つ一つが濃密なので、本記事ではあまり深入りはしませんが、「それらがどういう旨みを持ってT3 Stackを成しているのか」、「少し動かしたことがあるよ」と読み終わる頃には人に説明できるようまとめてみました。

キーワードは **full-stack typesafety(フルスタックな型安全)** です。📝

# T3 Stack

T3 Stack とは、[Theo](https://twitter.com/t3dotgg) 氏によって提唱された Web 開発技術スタックで、以下の思想に焦点を当てています。

- simplicity(シンプルさ)
- modularity(モジュール性)
- full-stack typesafety(フルスタックな型安全)

> The _“T3 Stack”_ is a web development stack made by [Theo](https://twitter.com/t3dotgg) focused on simplicity, modularity, and full-stack typesafety.

https://create.t3.gg/en/introduction

そして本思想を実現するため以下 6 つの技術スタックが採用されています。

- Next.js
- TypeScript
- tRPC
- Prisma
- TailwindCSS
- NextAuth.js

![includes.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/cf60f59a-5465-bdd3-4887-b781de1bfa77.png)
引用：[Create T3 App](https://create.t3.gg/)

これら技術スタックから推測できる通り、TypeScript を前提とすることで **型安全な** Web アプリ開発を目指し、Next.js を用いて Web アプリを組み立てていくということになります。

上記はあくまでも最小構成であり、プロジェクトの要件に応じてその他ライブラリの導入を検討しても構いません。
e.g.) 状態管理であれば、 [Zustand](https://github.com/pmndrs/zustand) や [Jotai](https://github.com/pmndrs/jotai) など

https://create.t3.gg/en/other-recs

# T3 Stack を実現する技術スタック

## Next.js

https://nextjs.org/

Next.js は、React をベースとしたフルスタックな Web アプリケーションフレームワークです。React 公式ドキュメント [react.dev](https://react.dev/) が今年 23 年 3 月に発表されました[^1] が、React そのものはライブラリであり、単体ではルーティングやデータフェッチの機能を持たないため、アプリ全体を構築する場合の推奨として Next.js が挙げられています。React エコシステムを用いたアプリケーション構築のデファクトスタンダードとなることが想像できます。

## TypeScript

https://www.typescriptlang.org/

TypeScript は altJS として Microsoft が 2012 年に開発した静的型付言語です。昨今主流となっているフロントエンドフレームワーク(React, Vue, Svelte 等)では、TypeScript の利用が推奨されています。

## tRPC

https://trpc.io/

tRPC は、TypeScript で実現する RPC(RemoteProcedureCall) 技術 で、スキーマ定義やクエリ言語を用いることなくフロント/バックエンド間の通信を型安全に行います。[^2]

プロジェクトが TypeScript でフルスタックな構築を想定していれば、サーバ/クライアントで直接型を共有することができるため、従来のような OAS(OpenAPI Specification)によるスキーマ定義を用いて OpenAPI generator でコード生成を行う工程が不要となります。またドキュメント作成や管理にかかる手間も大幅に削減できます。

ちなみに tRPC は、[JavaScript ライジングスター(2022)-バックエンド](https://risingstars.js.org/2022/ja#section-nodejs-framework) や [State of JavaScript(2022)-Data Fetching](https://2022.stateofjs.com/en-US/other-tools/#data_fetching) で上位にランクインし、注目されつつあります。

ここでも Theo 氏のコメントが...

![stateofjs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/60b1d3da-59dd-d64f-1361-b882b8adb81f.png)
引用：[State of JavaScript(2022)-Libraries](https://2022.stateofjs.com/en-US/other-tools/#libraries)
## Prisma

https://www.prisma.io/

Prisma は、Node.js と TypeScript による型安全な ORM(Object Relational Mapping) です。

DB スキーマを定義することで DB のモデルとアプリケーションのモデルで整合性をとることができ、関数の自動補完やデータ型の定義など TypeScript の強みをそのまま生かして DB 操作することができます。

デフォルトは SQLite ですが、PostgreSQL や MySQL、MongoDB など自ら管理している既存の DB に導入することも可能です。

## Tailwind CSS

https://tailwindcss.com/

Tailwind CSS は、ユーティリティファーストを謳った CSS フレームワークです。フレームワーク内で定義済みの class(ユーティリティクラス)を自由に組み合わせることでスタイルを適用します。

バニラ CSS(素の CSS)とユーティリティが似ているため、CSS の知識が多少あれば実装にとっかかりやすく、class 名を都度考える必要がないことによる開発プロセスの高速化、ユーティリティクラスによる再利用可能な設計による CSS ファイルサイズの肥大化抑止に期待できます。[^3]

[State of CSS(2023)-Ratio Over Time](https://2023.stateofcss.com/en-US/css-frameworks/#css_frameworks_experience_linechart) でもその人気が伺えます。

![stateofcss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/adffb0b3-9e67-7bfb-a6af-b1a92e080010.png)


## NextAuth.js

https://next-auth.js.org/

NextAuth.js は、名称からも読み取れる通り Next.js で認証機能を実装するためのライブラリです。Google や Facebook、Apple など主要なプロバイダによる OAuth1.0 や OAuth2.0 認証をサポートしており、データベースセッションや JWT によるセッション管理方式を選択することができます。

# create-t3-app (雛形プロジェクト作成)

上述の[T3 Stack を実現する技術スタック](#t3-stack-を実現する技術スタック)で触れた各技術スタックを導入した Next.js のセットアップを効率的に行うために、CLI `create-t3-app` が提供されています。

ここでは、CLI を触ってみて T3 Stack に則ったプロジェクト雛形を作成し、実物を通し見ることで噛み砕いてきたいと思います。

https://create.t3.gg/

## 実行環境

記事執筆時点の Node.js v20 LTS で実行しました。

```shell
$ node -v
v20.10.0
$ npm -v
10.2.3
```

## create コマンド実行

初めて実行する場合は、install から促してくれます。  
本記事投稿時点では、最新 v7.25.0 のようです。

```shell
$ npm create t3-app@latest
Need to install the following packages:
  create-t3-app@7.25.0
Ok to proceed? (y)
```

以下のように、作成するプロジェクト名(任意)や用いる言語(TS or JS)等、上述の技術スタックを順に聞かれるので設定を進めます。今回は全部盛りでお試しです。

```shell
   ___ ___ ___   __ _____ ___   _____ ____    __   ___ ___
  / __| _ \ __| /  \_   _| __| |_   _|__ /   /  \ | _ \ _ \
 | (__|   / _| / /\ \| | | _|    | |  |_ \  / /\ \|  _/  _/
  \___|_|_\___|_/‾‾\_\_| |___|   |_| |___/ /_/‾‾\_\_| |_|


│
◇  What will your project be called?
│  test-my-t3-app
│
◇  Will you be using TypeScript or JavaScript?
│  TypeScript
│
◇  Will you be using Tailwind CSS for styling?
│  Yes
│
◇  Would you like to use tRPC?
│  Yes
│
◇  What authentication provider would you like to use?
│  NextAuth.js
│
◇  What database ORM would you like to use?
│  Prisma
│
◇   EXPERIMENTAL  Would you like to use Next.js App Router?
│  Yes
│
◇  Should we initialize a Git repository and stage the changes?
│  Yes
│
◇  Should we run 'npm install' for you?
│  Yes
│
◇  What import alias would you like to use?
│  ~/

Using: npm

✔ test-my-t3-app scaffolded successfully!

Adding boilerplate...
✔ Successfully setup boilerplate for nextAuth
✔ Successfully setup boilerplate for prisma
✔ Successfully setup boilerplate for tailwind
✔ Successfully setup boilerplate for trpc
✔ Successfully setup boilerplate for envVariables

Installing dependencies...
✔ Successfully installed dependencies!

Initializing Git...
✔ Successfully initialized and staged git
```

:::note info
Next.js 13(v13.4) から安定版が導入された _App Router_ が選択できるようになっていました。設定(挑戦)のお礼と改善 Issue の Welcomeメッセージが表示されました。😇
```shell
Thank you for trying out the App Router option. 
If you encounter any issues, please open an issue!
```

:::

## 起動前準備

### DB設定

今回は Prisma を含めているため、Prisma スキーマを DB と同期させる必要があります。
前述の通り、SQLite(デフォルト設定)でDBが作成されていることがわかりますね。

```shell
$ npm run db:push

Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "db.sqlite" at "file:./db.sqlite"

SQLite database db.sqlite created at file:./db.sqlite

🚀  Your database is now in sync with your Prisma schema. Done in 124ms

✔ Generated Prisma Client (v5.7.1) to ./node_modules/@prisma/client in 465ms
```

### 認証設定

次に NextAuth.js を有効にしたので、プロバイダの設定が必要です。雛形プロジェクトでは、認証プロバイダとしてDiscordを用いる`DiscordProvider`の設定を行います。
[Create T3 App公式Docs手順](https://create.t3.gg/en/usage/first-steps#authentication) に沿って、取得したCLIENT ID/SECRETSを.envファイルにそれぞれ設定します。
```.env
DISCORD_CLIENT_ID="1234567890"
DISCORD_CLIENT_SECRET="XXXXXX"
```
:::note info
Discord以外の認証プロバイダを利用したい場合(built-in OAuthプロバイダ：GitHubやGoogle等、自作プロバイダ等)は、[NextAuth.js 公式Docs - Providers](https://next-auth.js.org/providers/) を参照のこと。
:::

:::note alert
生成したシークレット情報は、Gitなどに公開しないようご注意ください。
:::


## 開発サーバ起動
これで準備が整ったので、開発サーバを起動してみます。

```shell
$ npm run dev
```

localhost:3000 で画面表示されれば起動完了です。

![t3app_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/6e9c5f3c-b07d-7d89-af86-71a4cf22fd5a.png)

せっかく認証機能も追加したので、 **Sign in** してみたいと思います。

### 認証確認

クリックすると、前準備で設定したアカウントによるアクセス要求の確認画面が開くのでそのまま認証します。（qiita_ym はテストアカウントなのでご心配なく）

![signin_discord.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/0cf65d29-467d-9e06-b9aa-04012d3bb981.png)

すると、画面中央にログインユーザのアカウント名が表示されてログイン成功です。🚀

![t3app_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/49d4ac8b-12bd-f19e-25b1-3d774ccb0b64.png)

### DB確認

Prismaを導入すると、PrismaStudioも併せて導入されます。これによりブラウザ上でGUIによるDB操作が可能となります。

ログインしたユーザ情報がDBに格納されているかを見てみましょう。

```shell
$ npm run db:studio
```

localhost:5555 でPrisma Studioを起動できます。

![prisma_studio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/09e7b258-e3ab-1b28-b11e-802483ac9c63.png)

**User** を確認すると、先ほどログインしたユーザ情報が格納されていることがわかりますね。

![prisma_studio_user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017966/d172c9c3-6126-b440-20cd-7ed054c7c7d1.png)


## プロジェクト構成

createコマンドによる雛形プロジェクトは以下の構成でした。
ベースとなる Next.js に tRPC や Prisma 、 NextAuth.js が追加されているということがわかります。またコードフォーマットの Prettier や静的コードチェックの ESLint がデフォルトで入っているのはいいですね。

install された Next.js のバージョンは v14.0.4 で、[最新バージョン](https://github.com/vercel/next.js/releases/tag/v14.0.4)(本記事投稿時点)が入っていたことに驚きました。素晴らしい追随力ですね。

```
test-my-t3-app/
├── node_modules/
├── prisma/                         // Prisma関連
│   ├── db.sqlite
│   └── schema.prisma
├── public/
│   └── favicon.ico
├── src/
│   ├── app/
│   │   ├── _components/
│   │   │   └── create-post.tsx
│   │   ├── api/
│   │   │   ├── auth                // NextAuth.js関連
│   │   │   │   └── [...nextauth]
│   │   │   │       └── route.ts
│   │   │   └── trpc
│   │   │       └── [trpc]
│   │   │           └── route.ts
│   │   ├── layout.tsx
│   │   └── page.tsx
│   ├── server/
│   │   ├── api/
│   │   │   ├── root.ts
│   │   │   ├── routers
│   │   │   │   └── post.ts
│   │   │   └── trpc.ts
│   │   ├── auth.ts
│   │   └── db.ts
│   ├── styles/
│   │   └── globals.css
│   ├── trpc/                       //tRPC関連
│   │   ├── react.tsx
│   │   ├── server.ts
│   │   └── shared.ts
│   └── env.js
├── .env
├── .env.example
├── .eslintrc.cjs
├── .gitignore.js
├── next.env.d.js
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.cjs
├── prettier.config.js
├── README.md
├── tailwind.config.ts              // Tailwind CSS関連
└── tsconfig.json
```

# おわりに

T3 Stack について、そもそもの概念と用いる要素技術を取り上げると共に、雛形プロジェクトを動かしてみました。今回は紙幅の都合上、具体的な実装については触れられていませんので、いずれ各技術スタックに着目して型安全なフルスタック Web アプリケーションを実装、ご紹介できればと思います。T3 Stackは、現場レベルで主流とはまだ言い難いのでこれからの世間動向に目が離せませんね。

ここまでご覧いただきありがとうございました。
明日はイブです。素敵なクリスマスをお過ごしください。🎄

[^1]: 公式Blog https://ja.react.dev/blog/2023/03/16/introducing-react-dev
[^2]: 現在 TypeScript を用いた型安全な API 実装は GraphQL が主流ですが、GraphQL 自体が言語に依存しない設計故に TypeScript の強みを全て享受することはできないと言われています。
[^3]: ユーティリティクラスを組み合わせることで指定するクラス数が多くなり、可読性が落ちてしまうと懸念はあります。