😎

先取りTanStack Start

2024/07/09に公開

TanStackのリポジトリを読んでいたらTanStack Startのドキュメントの最初のバージョンがpushされたようなのでチェックします。

https://tanstack.com/router/latest/docs/framework/react/guide/tanstack-start

TanStack Startとは

TanStack Startは、TanStack Routerをベースにしたメタフレームワークとかフルスッタックフレームワークとか分類されるものです。

サーバーレンダリングされたReactアプリケーションを構築できて、TanStack Router、Nitro(サーバー用)、Vite(開発用)の上に構築されています。

Solid Startと同じくVinxiを基盤に開発されています。

ニーズとしてはクライアントサイドにRouterを使っているアプリケーションでサーバーサイドレンダリング(SSR)も必要になったタイミングで導入します。

サンプルアプリケーションはRouterとFormのリポジトリにあります。以下をブラウザで動作を確認できます。

https://tanstack.com/router/latest/docs/framework/react/examples/start-basic

ただ各API使い方はFormリポジトリ内ののサンプルのがわかりやすいです。以下にあります

https://github.com/TanStack/form/tree/48456a98edd5901f6bb24950573bda750cc68f8e/examples/react/tanstack-start

Routerのユーザーなら想像に難しくなくサーバー用のエントリポイントのファイルがビルドに一個増えただけです(はじめ方は前述のドキュメントを参照)。

現在、tanstack.comでも使用されておりドッグフーディングされてます。これのデプロイ先はVercelです(なのでNode.jsの環境で動いているのだと思われる)。

https://github.com/TanStack/tanstack.com

実装は現在Routerのリポジトリ内に存在しており、packages/start/以下で確認できます。

https://github.com/TanStack/router/tree/08d3e61b4c9652d37a6685f37e8d366762b2633e/packages/start

Vinxiについて

https://github.com/nksaraf/vinxi

Vinxiは「メタ・ルーター」または「ルーター・マネージャー」であり、サーバーとクライアントのルーターを一元的な設定でまとめることができます。

Vite(開発サーバーとバンドル)とNitro(HTTPサーバー)の上に構築されており、SolidStartコミッタのNikhil Sarafによって作られました。

これを使って好みのパーツ同士で独自のウェブフレームワークが作れるというクラフトマンシップに基づいたツールだと私は受け取りました。

TanStack StartではViteの代わりに使用でき、先のサンプルどうり、app.config.tsファイルを用意してvinxi startでサーバーを起動します。

Server Functionsについて

createServerFnという関数に処理を渡すことでServer Functionsを定義できます。

RemixとNext.jsのAction/Server Actionsに相当し、必ずサーバーで実行されます。

https://tanstack.com/router/latest/docs/framework/react/guide/server-functions

内部実装的にはVite PluginがこのアノテーションがついたコードをBabelでトランスパイルします。

TanStack Formのサンプルでは、フォームの送信先をAPIではなくこのラップしたコードにしています。HTMLネイティブフォームのactionに.urlを文字列として与えることが可能です。

https://github.com/TanStack/form/blob/48456a98edd5901f6bb24950573bda750cc68f8e/examples/react/tanstack-start/app/utils/form.tsx#L24-L45

https://github.com/TanStack/form/blob/48456a98edd5901f6bb24950573bda750cc68f8e/examples/react/tanstack-start/app/routes/index.tsx#L13-L62

ハイドレーション

<StartClient>というコンポーネントを使用します。

サーバーサイドのエントリーポイントでcreateStartHandler を通して事前に生成されたroutes定義をSSRで配信し、クライアントサイドでも同じ定義を読み込んでhydrateRoot()できるという魔法のような仕組みがあります。

https://github.com/TanStack/form/blob/48456a98edd5901f6bb24950573bda750cc68f8e/examples/react/tanstack-start/app/client.tsx#L1-L7

Loader

Route.useLoaderData()を使用することで、クラサバ両方でデータ読み込みを解決できます(Remixのloaderに相当)。

前述のcreateServerFnで定義した読み込みクエリをRouteに設定しておきます。

https://github.com/TanStack/router/blob/08d3e61b4c9652d37a6685f37e8d366762b2633e/examples/react/start-basic/app/utils/posts.tsx#L11-L25

https://github.com/TanStack/router/blob/08d3e61b4c9652d37a6685f37e8d366762b2633e/examples/react/start-basic/app/routes/posts.tsx#L4-L38

Discussion