solid-start について
`@tanstack/solid-start`を使う開発者向けに、TanStack StartのSolidバインディングとアプリ構築を解説します。セットアップ、サーバー関数、ルーティングAPI、Solid固有のパターンを扱います。
主な機能
- 01TanStack StartのSolid向け設定
- 02`useServerFn`によるサーバー関数呼び出し
- 03ルーターフックとコンポーネント
- 04アイソモーフィック処理とサーバー専用処理
- 05型推論とプロジェクト設定の案内
活用シーン
- 01SolidベースのTanStack Startアプリの開始
- 02Solidコンポーネントからのサーバー関数呼び出し
- 03型付きルートデータとナビゲーションの利用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tanstack/ router --skill solid-startインストール後、Claude Code で/solid-startを入力して読み込まれたか確認します。
詳細
Solid Start (@tanstack/solid-start)
このスキルは start-core を基盤としています。基礎概念については、まず @tanstack/start-client-core#start-core をお読みください。
このスキルでは、TanStack Start の Solid 固有のバインディング、セットアップ、パターンについて説明します。
CRITICAL:すべてのコードはデフォルトでアイソモーフィックです。ローダーはサーバーとクライアントの両方で実行されます。サーバー専用のロジックには
createServerFnを使用してください。
CRITICAL:
@tanstack/solid-startと SolidStart(@solidjs/start)を混同しないでください。これらは API の異なる、まったく別のフレームワークです。
CRITICAL:型は完全に推論されます。推論された値をキャストしたり、型注釈を付けたりしないでください。
パッケージ API の概要
@tanstack/solid-start は @tanstack/start-client-core のすべての機能に加え、以下を再エクスポートします。
useServerFn— コンポーネントからサーバー関数を呼び出すための Solid フック
すべてのコア API(createServerFn、createMiddleware、createStart、createIsomorphicFn、createServerOnlyFn、createClientOnlyFn)を @tanstack/solid-start から利用できます。
サーバーユーティリティ(getRequest、getRequestHeader、setResponseHeader、setCookie、getCookie)は @tanstack/solid-start/server からインポートします。
プロジェクト全体のセットアップ
1. 依存関係をインストールする
npm i @tanstack/solid-start @tanstack/solid-router solid-js
npm i -D vite vite-plugin-solid typescript
2. package.json
{
"type": "module",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"start": "node .output/server/index.mjs"
}
}
3. tsconfig.json
{
"compilerOptions": {
"jsx": "preserve",
"jsxImportSource": "solid-js",
"moduleResolution": "Bundler",
"module": "ESNext",
"target": "ES2022",
"skipLibCheck": true,
"strictNullChecks": true
}
}
4. vite.config.ts
import { defineConfig } from 'vite'
import { tanstackStart } from '@tanstack/solid-start/plugin/vite'
import solidPlugin from 'vite-plugin-solid'
export default defineConfig({
plugins: [
tanstackStart(), // MUST come before solid plugin
solidPlugin({ ssr: true }),
],
})
5. ルーターファクトリー(src/router.tsx)
import { createRouter } from '@tanstack/solid-router'
import { routeTree } from './routeTree.gen'
export function getRouter() {
const router = createRouter({
routeTree,
scrollRestoration: true,
})
return router
}
6. ルートルート(src/routes/__root.tsx)
import {
Outlet,
createRootRoute,
HeadContent,
Scripts,
} from '@tanstack/solid-router'
import { HydrationScript } from 'solid-js/web'
import { Suspense } from 'solid-js'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My TanStack Start App' },
],
}),
// shellComponent renders the HTML document shell (always SSR'd)
shellComponent: RootDocument,
})
function RootDocument(props: { children: any }) {
return (
<html>
<head>
<HydrationScript />
</head>
<body>
<HeadContent />
<Suspense>{props.children}</Suspense>
<Scripts />
</body>
</html>
)
}
7. インデックスルート(src/routes/index.tsx)
import { createFileRoute } from '@tanstack/solid-router'
import { createServerFn } from '@tanstack/solid-start'
const getGreeting = createServerFn({ method: 'GET' }).handler(async () => {
return 'Hello from TanStack Start!'
})
export const Route = createFileRoute('/')({
loader: () => getGreeting(),
component: HomePage,
})
function HomePage() {
const greeting = Route.useLoaderData()
return <h1>{greeting()}</h1>
}
useServerFn フック
useServerFn を使用すると、リダイレクト処理を自動で行い、Solid コンポーネントからサーバー関数を呼び出せます。
import { createServerFn, useServerFn } from '@tanstack/solid-start'
import { createSignal } from 'solid-js'
const updatePost = createServerFn({ method: 'POST' })
.validator((data: { id: string; title: string }) => data)
.handler(async ({ data }) => {
await db.posts.update(data.id, { title: data.title })
return { success: true }
})
function EditPostForm(props: { postId: string }) {
const updatePostFn = useServerFn(updatePost)
const [title, setTitle] = createSignal('')
return (
<form
onSubmit={async (e) => {
e.preventDefault()
await updatePostFn({ data: { id: props.postId, title: title() } })
}}
>
<input value={title()} onInput={(e) => setTitle(e.target.value)} />
<button type="submit">Save</button>
</form>
)
}
React 版とは異なり、useServerFn は返される関数をメモ化しません(Solid の setup は一度だけ実行されるため、useCallback に相当する機能は不要です)。
Solid 固有のコンポーネント
@tanstack/solid-router のルーティングコンポーネントは、すべて Start で動作します。
<Outlet>— マッチした子ルートをレンダリングします<Link>— 型安全なナビゲーション<Navigate>— 宣言的なリダイレクト<HeadContent>—@solidjs/metaを使って head タグをレンダリングします(ポータルで<head>に挿入するため、<body>内に配置する必要があります)<Scripts>— body スクリプトをレンダリングします(<body>内に配置する必要があります)<Await>—<Suspense>で遅延データをレンダリングします<ClientOnly>— ハイドレーション後にのみ子要素をレンダリングします<CatchBoundary>—Solid.ErrorBoundaryでラップするエラーバウンダリー
フックのリファレンス
@tanstack/solid-router のフックは、すべて Start で動作します。ほとんどのフックは Accessor<T> を返します。値を読み取るにはアクセサーを呼び出してください。
useRouter()— ルーターインスタンス(Accessor ではありません)useRouterState()—Accessor<T>。ルーターの状態を購読しますuseNavigate()— ナビゲーション関数(Accessor ではありません)useSearch({ from })—Accessor<T>。検証済みの検索パラメーターuseParams({ from })—Accessor<T>。パスパラメーターuseLoaderData({ from })—Accessor<T>。ローダーデータuseMatch({ from })—Accessor<T>。完全なルートマッチuseRouteContext({ from })—Accessor<T>。ルートコンテキストRoute.useLoaderData()—Accessor<T>。型付けされたローダーデータ(ルートファイルでの使用を推奨)Route.useSearch()—Accessor<T>。型付けされた検索パラメーター(ルートファイルでの使用を推奨)
よくある間違い
1. CRITICAL:誤ったパッケージからインポートする
// WRONG — this is the SPA router, NOT Start
import { createServerFn } from '@tanstack/solid-router'
// CORRECT — server functions come from solid-start
import { createServerFn } from '@tanstack/solid-start'
// CORRECT — routing APIs come from solid-router (re-exported by Start too)
import { createFileRoute, Link } from '@tanstack/solid-router'
2. CRITICAL:Accessor の呼び出しを忘れる
ほとんどのフックは Accessor<T> を返します。値を読み取るには呼び出す必要があります。
// WRONG
const data = Route.useLoaderData()
return <h1>{data.message}</h1>
// CORRECT
const data = Route.useLoaderData()
return <h1>{data().message}</h1>
3. HIGH:Scripts コンポーネントがない
ルートルートの <body> に <Scripts /> がないと、クライアントの JavaScript が読み込まれず、アプリはハイドレーションされません。
4. HIGH:Vite 設定で Solid プラグインを Start プラグインより前に配置する
// WRONG
plugins: [solidPlugin(), tanstackStart()]
// CORRECT
plugins: [tanstackStart(), solidPlugin()]
関連項目
@tanstack/start-client-core#start-core— Start のコア概念@tanstack/router-core#router-core— ルーティングの基礎@tanstack/solid-router#solid-router— Solid Router のフックとコンポーネント