今更ながらTypeScriptで話題になっているT3 Stackについて調べてみました。
ちょうど現在、新しいプロジェクトを始める予定のため、新しいアーキテクチャを試そうということで調べつつまとめてみました。

T3 Stackとは

T3 Stackは、公式サイトに"Typesafe From The Start"と書いている通り、モジュール性を妥協することなく型安全にしたフレームワークです。
T3 Stackの構成は以下のようになっています。

  • Next.js = Reactのメタフレームワーク
  • TypeScript = 型安全なJavaScript派生言語
  • tRPC = コード生成なしでクライアントとバックエンドでスキーマ共有
  • Prisma = TypeScriptから使いやすいORM(データベース操作)
  • Tailwind CSS = ユーティリティファーストなCSSフレームワーク
  • NextAuth.js = Next.jsから直接認証を実装できるライブラリ

このように、自ら何かを追加しなくても、ある程度のWebアプリケーションならT3 Stackで解決できるでしょう。

T3 Stackの良いところ

フレームワークを形作る構成を見れば予想もつきそうなところではありますが、調べてみて「ここ良いな」と感じた点をまとめます。

  1. 型安全を前面に押し出しているところ
  2. エッジDBなどの新しいDB技術ではなくSQL(Prisma)を使うところ
  3. BFFを前提にしているためコンパクトに雛形がまとまっているところ
  4. デフォルトで .env をサポートしているところ
  5. npm, yarn, pnpm, bunと主要なバンドラーをカバーしているところ

必要最小限ではありますが、こういった開発指針がわかりやすいおかげで余計なことを考えずに済みます。

実用性を考えてみる

ここまで見てきたところ、特に欠点らしい欠点が見られないT3 Stackですが、実用性はどうでしょうか。

こういったフレームワークをさらにフレームワーク化(React -> Next.js -> T3 Stack)する試みで心配なのはやはり拡張性です。
T3 Stackも、基本的には他のライブラリを追加しないことを前提としている部分があるため、T3 Stackの枠外に出ない前提であれば実用性があると言えるでしょう。

一言でまとめれば「コンパクトでシンプルな認証付きWebアプリ」であればプロダクトレベルでも使えると言って良いという感想です。

簡単にT3 Stackを触ってみる

公式ドキュメントに書いてある通り、さまざまなパッケージ管理ツールやバンドラーでインストールできますが、今回はpnpmを利用します。

shell
pnpm create t3-app@latest

こちらを実行すると以下のようなプロンプトでプロジェクトを作成できます。それぞれの質問文に対して日本語訳をつけています。

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



  What will your project be called? # プロジェクト名はなんですか?
  tanapod

  Will you be using TypeScript or JavaScript? # TS/JSどちらを使いますか?
  TypeScript

  Will you be using Tailwind CSS for styling? # Tailwind CSSを使いますか?
  Yes

  Would you like to use tRPC? # tRPCを使いますか?
  Yes

  What authentication provider would you like to use? # 認証プロバイダは何を使いますか?
  NextAuth.js

  What database ORM would you like to use? # ORMは何を使いますか?
  Prisma

  Would you like to use Next.js App Router? # Next.jsのApp Routerを使いますか?
  Yes

  What database provider would you like to use? # データベースは何を使いますか?
  PostgreSQL

  Should we initialize a Git repository and stage the changes? # Gitリポジトリを初期化して変更をステージングしますか?
  Yes

  Should we run 'pnpm install' for you? # pnpm installを実行しますか?
  Yes

  What import alias would you like to use? # インポートエイリアスは何を使いますか?
  @/

Using: pnpm

 tanapod 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 dbContainer
 Successfully setup boilerplate for envVariables
 Successfully setup boilerplate for eslint

Installing dependencies...
 Successfully installed dependencies!

Initializing Git...
 Successfully initialized and staged git

Next steps:
  cd tanapod
  Start up a database, if needed using './start-database.sh'
  pnpm db:push
  pnpm dev
  git commit -m "initial commit"

サクッと完了するので、プロジェクトに移動して内容を確認します。

shell
$ cd <プロジェクト>
$ tree -I node_modules -L 2
.
├── README.md
├── next-env.d.ts
├── next.config.js
├── package.json
├── pnpm-lock.yaml
├── postcss.config.cjs
├── prettier.config.js
├── prisma
│   └── schema.prisma
├── public
│   └── favicon.ico
├── src
│   ├── app
│   ├── env.js
│   ├── server
│   ├── styles
│   └── trpc
├── start-database.sh
├── tailwind.config.ts
└── tsconfig.json

シンプルな内容になっていますが、このままいくつかのコマンドでプロジェクトを開始できます。
プロンプトで表示されたメッセージに従ってコマンドを入力していきます。

shell
$ ./start-database.sh # Dockerでデータベースが立ち上がる
$ pnpm db:push # .envやスキーマファイルのロード
$ pnpm dev # 開発環境立ち上げ

今回は pnpm dev の時点で以下のようなエラーが出ました。

shell
 Invalid environment variables: {
  DISCORD_CLIENT_ID: [ 'Required' ],
  DISCORD_CLIENT_SECRET: [ 'Required' ]
}

どうやらデフォルトでDiscord認証を設定するようにされているようなので、 src/env.js の中身を修正します。 DISCORD_CLIENT_IDDISCORD_CLIENT_SECRET をコメントアウトします。

src/env.js
// 前略
    NEXTAUTH_URL: z.preprocess(
      // This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
      // Since NextAuth.js automatically uses the VERCEL_URL if present.
      (str) => process.env.VERCEL_URL ?? str,
      // VERCEL_URL doesn't include `https` so it cant be validated as a URL
      process.env.VERCEL ? z.string() : z.string().url()
    ),
    // DISCORD_CLIENT_ID: z.string(), // ここをコメントアウト
    // DISCORD_CLIENT_SECRET: z.string(), // ここをコメントアウト
// 後略

これで pnpm dev で起動し、 http://localhost:3001/ にブラウザでアクセスすればT3 Stackが立ち上がります。

T3 Stackへの所感

まだ十分に触ったと言えませんが、コンパクトさとシンプルさは非常に好感触です。
ライブラリ選定の自由度や拡張性という意味でいえば縛りを感じますが、それが逆にすべきことに集中させてくれます。

せっかくなのでしばらくT3 Stackで新しいプロジェクトを走らせてみて、Tipsや続きの感想ができたらこのコンテンツに書き足していこうと思います。