最近ちょっと気になってるフレームワークがある。
「TanStack Start」です。
Reactベースのフルスタックフレームワークで、最近「Next.js一強じゃなくなってきたよね」みたいな話の中でちょくちょく名前を見るようになってきたやつですね。
「Next.jsちょっと下火じゃね?」みたいな意見とともに最近ネットでよく名前見るあいつです。
現在はRC(Release Candidate)段階ですが、公式ではfeature-complete、APIもstableとされていますね。
TanStack Startってなんや?
めちゃくちゃ雑に言うと、
という構成のReactベースのフルスタックフレームワークです。
SSR、Streaming、Server Functions、Server Routes、Middlewareなど、今どきのフルスタックフレームワークに欲しいものは一通り揃っています。
そして名前の通り、ルーティングの中心にいるのが「TanStack Router」。
TanStack Routerは型安全なルーティングがかなり強いです。
例えば、
<Link
to="/users/$userId"
params={{ userId: "123" }}
>
User
</Link>
みたいなルートのパラメータまでTypeScriptの型システムに乗せられます。
「URLなんてただの文字列でしょ」
ではなく、
「URL・パラメータ・Search Paramsまでアプリケーションの型として扱っていこうぜ!」
という思想ですね。
いいね、クールだ。型安全性が高いのは素晴らしいね!!
そしてViteで動く!!
個人的に嬉しいポイント。
Viteで動く!!
Next.jsは独自のビルドシステムを持っていますが、TanStack StartはViteをサポートしています。
VueのフルスタックフレームワークであるNuxtもViteで動くのに、
「なんでNext.jsはViteじゃないんだ……」
と若干モヤモヤしていた私には嬉しい。
Vite、好き。HMR使いやすいよねぇ。
そしてServer Entry Pointを見ると、、、
TanStack StartのServer Entry Pointは、こんな感じになっています。
export default {
fetch(req: Request) {
// ...
},
}
はい、「fetch Handler」のご登場でございます。
Web標準のRequestとResponseを使ったUniversal Fetch Handler形式になっています。
いいねぇWeb標準、余談ですがJS/TSののバックエンドフレームワークのHonoが好きな理由もここです。
依存が少ないことは素晴らしい。できるだけ標準で完結させて必要な部分だけミドルウェア的に追加していきたい思想の私には刺さります。
公式ドキュメントにも、
commonly used by Cloudflare Workers and other WinterCG-compatible runtimes
とあります。
おん、、?
Cloudflare Workers、、?
WinterCG互換ランタイム、、!?
え、Cloudflare?????
そう!!!Cloudflare Workersです!!!!
きましたCloudflareこいつを待ってた。
TanStack Start、Cloudflare Workersとめちゃくちゃ相性いいんすわ。
Cloudflare公式でもTanStack Startがサポートされています。
しかもCloudflare Workers向けには、
npm create cloudflare@latest -- my-tanstack-start-app --framework=tanstack-start
これで作れます。
既存プロジェクトなら、
npm i -D @cloudflare/vite-plugin wrangler
して、
// vite.config.ts
import { defineConfig } from "vite"
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
import { cloudflare } from "@cloudflare/vite-plugin"
import react from "@vitejs/plugin-react"
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: "ssr" } }),
tanstackStart(),
react(),
],
})
つまり「Cloudflare Vite Plugin経由でそのままWorkersの世界に入れる」っちゅーことです。
Viteに対応してるって素晴らしいね、やっぱりフレームワークから独立した共通基盤ってのが強い。
Next.jsやとどないやねん
もちろんNext.jsもCloudflare Workersで動かせます。
ただ、Next.jsの場合は、
という形で、OpenNextのAdapterを利用します。
対してTanStack Startなら、
というかなり素直な構成。
しかもTanStack Start自体のServer Entry PointがUniversal Fetch Handler形式。
Cloudflare Workers側もfetch(Request)。
思想からして近いんですよ。
つまりCloudflareのサービスをそのまま使える
Cloudflare Workers上で動くということは、
TanStack Start (on Cloudflare Workers)
│
├── D1
├── KV
├── R2
├── Durable Objects
├── Queues
└── Workers AI
みたいな構成も当然狙えるっちゅーわけです。
Cloudflare Vite PluginではWorkers Runtime APIやBindingsへ直接アクセスできます。
つまり、
的な雰囲気で、フロントエンドからバックエンド、DBまでCloudflareに寄せたフルスタックWebアプリが作れる。
はい、Cloudflare教の皆さんはもう使いましょう。そうでない皆さんも一旦入信しときましょう。
し!か!も!
個人的にTanStack Startで好きなのが、「Server Function」という境界がかなり分かりやすいところ。
例えば、
const getUser = createServerFn({
method: "GET",
}).handler(async () => {
return await db.users.find(...)
})
こういう処理はサーバーで実行されます。
なので、
という境界が見えやすい。
もちろんTanStack StartでもReactなので.tsxは普通に使いますし、SSRもします。
なので、「TanStack Startならバックエンドでtsxを書かなくていい!」というわけではありません。
が、
routes/
users.tsx
server/
users.ts
auth.ts
db.ts
のように、UIとサーバー側のロジックを分けて書く設計はかなりやりやすい。
個人的には、
.tsx → Reactを書くところ
.ts → サーバーロジックなどJSXを書かないところ
という感覚で整理しやすいのが嬉しいです。
Next.jsの設計思想に不満持ってた皆さん、ほらほら、Reactの既存資産活かしたままNuxtのような素直な構成やりやすいすよ、ついでにCloudflare教入って行きません?個人開発者にとっては神サービスすよ??
Next.js終わった?
まぁ下火と言われてる通り正直Tanstack Startが成熟していけばNext.js使ってた層が乗り換えることはあり得るでしょうね。
ただNext.jsは依然として巨大ですし、エコシステムも成熟しています。
一方TanStack Startは、この記事を書いている時点ではまだRCです。
が、昔はReactでフルスタック?
ほなNext.js使ってVercelとちゃうかー
だったところに、
ほなTanStack StartでCloudflare Workersかー
みたいな選択肢がかなり現実的になってきたっちゅー話です。
「Reactフルスタック=とりあえずNext.js」ではなくなりつつある、という意味では、めちゃくちゃ面白い流れだと思います。