RC からの初の安定版は @tanstack/react-start / @tanstack/solid-start 1.169。型付きルーターを核に、ルート単位で SSR・サーバーでのデータ読み込み・クライアント描画を選べ、サーバー処理は createServerFn で明示する。コアは React に依存せず、RSC はオプトイン。

#移行・破壊的変更

Vite ビルド時は Vite 8 が必須。削除 API の差し替え先。

  • @tanstack/nitro-v2-vite-plugin → nitro()(nitro/vite)
  • useSession → iron-session などのセッションライブラリ
  • 新ライブラリは既存の Start セッション Cookie を読めない。Cookie 名の変更と再ログイン、または旧 Cookie を読む移行が必要
  • サーバー関数・ミドルウェアの .inputValidator() → .validator()
ts
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import { nitro } from 'nitro/vite'
import viteReact from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [tanstackStart(), nitro(), viteReact()],
})

レスポンスまわりは次のとおり。

  • setResponseStatus などのヘルパーは return / throw した Response より優先する
  • setResponseHeader('set-cookie', cookie) は送信中の Cookie をすべて置き換える。追加は setCookie か appendResponseHeader('set-cookie', cookie)
  • リダイレクトは redirect()。シリアライズされたサーバー関数の応答は Location などを載せない
  • 未捕捉エラーは 400〜599(既定 500)の汎用 JSON。固有のエラー本体が必要なら Response を返す
  • 不正なパーセントエンコードのパスはサーバーエントリより前に 400

#実行場所の明示

createIsomorphicFn はサーバーとブラウザで実装を並べ、使っていない側はバンドルから除く。ブラウザからの呼び出しはサーバーへ戻らない。サーバー呼び出しが欲しいときは createServerFn。

ts
import { createIsomorphicFn } from '@tanstack/react-start'
import { getRequest } from '@tanstack/react-start/server'

const getOrigin = createIsomorphicFn()
  .server(() => new URL(getRequest().url).origin)
  .client(() => window.location.origin)

// Call during a server request or in the browser.
const absoluteUrl = new URL('/about', getOrigin()).href

SSR のプロファイリングでは不要なサーバー作業を削りおおよそ 5.5 倍のスループットになった例。ホスティングは Vite と Nitro を軸に、Rsbuild も選べる。tanstack.com では Markdown とハイライトの見直し後に RSC を外した。エージェント向けの skills は npm パッケージに同梱。

#参考文献