mcpField
T
tanstack-start

tanstack-start

github.com/vercel-labs开发18.9k201 次安装1 天前更新
代码仓库

关于 tanstack-start

用于在 TanStack Start 中根据 json-render 规范生成并渲染完整页面与路由的 React 集成。它提供页面数据、元数据和静态路径服务端辅助函数,以及按路由匹配的回退界面。

主要功能

  1. 01在 TanStack Start 中渲染 json-render 页面
  2. 02定义路由模式和布局
  3. 03加载页面数据与元数据
  4. 04生成静态路径
  5. 05提供按路由匹配的加载与错误界面

适用场景

  1. 01根据应用规范构建页面
  2. 02加载参数化路由的数据
  3. 03为动态页面生成静态路径

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/vercel-labs/json-render --skill tanstack-start

安装后在 Claude Code 中输入/tanstack-start确认已加载。

详细介绍

@json-render/tanstack-start

当 TanStack Start 应用需要由 json-render 规范描述完整页面或路由时,使用此集成。

安装

npm install @json-render/core @json-render/react @json-render/tanstack-start

应用规范

将可在服务器端安全使用的内置定义加入生成目录。渲染器会提供这些定义的组件实现。

import { defineCatalog } from "@json-render/core";
import {
  schema,
  startComponentDefinitions,
} from "@json-render/tanstack-start/server";

const catalog = defineCatalog(schema, {
  components: {
    ...startComponentDefinitions,
    Card: cardDefinition,
    Shell: shellDefinition,
    Navigation: navigationDefinition,
    Home: homeDefinition,
    Post: postDefinition,
  },
  actions: {},
});

然后使用 StartAppSpec 和 TanStack Router 路由模式:

import type { StartAppSpec } from "@json-render/tanstack-start";

export const spec: StartAppSpec = {
  metadata: {
    title: { default: "Site", template: "%s | Site" },
  },
  layouts: {
    main: {
      root: "shell",
      elements: {
        shell: { type: "Shell", props: {}, children: ["nav", "slot"] },
        nav: { type: "Navigation", props: {}, children: [] },
        slot: { type: "Slot", props: {}, children: [] },
      },
    },
  },
  routes: {
    "/": {
      layout: "main",
      metadata: { title: "Home" },
      page: {
        root: "home",
        elements: {
          home: { type: "Home", props: {}, children: [] },
        },
      },
    },
    "/posts/$slug": {
      layout: "main",
      loader: "post",
      staticParams: [{ slug: "hello" }],
      page: {
        root: "post",
        elements: {
          post: {
            type: "Post",
            props: { value: { $state: "/post" } },
            children: [],
          },
        },
      },
    },
  },
};

命名参数使用 /posts/$slug,通配路由使用 /docs/$。通配路由加载器参数是以斜杠分隔的字符串,位于 _splat 下。生成 RFC 6902 补丁时,将路由键中的斜杠转义为 ~1。

每个布局都需要一个 Slot 元素。通过 startComponentDefinitions 声明 Slot 和 Link;无需要求使用者注册它们的 React 实现。

服务端辅助函数

import { createStartApp } from "@json-render/tanstack-start/server";

export const { getPageData, getHead, getStaticPaths } = createStartApp({
  spec,
  loaders: {
    post: async ({ slug }) => ({ post: await getPost(slug as string) }),
  },
});

状态合并优先级依次为应用状态、布局状态、页面状态,然后是加载器数据。getHead 会将应用和路由元数据合并到 TanStack 的 meta 和 links 描述符中。getStaticPaths 包含静态路由,以及带有 staticParams 的动态路由。将其字符串转换为 { path } 对象,以用于 TanStack Start 顶层的 pages 插件选项。加载器参数会进行 URL 解码,而 staticParams 中的值会在生成的路径中进行 URL 编码。路由匹配会将尾部斜杠视为可选项,并接受编码或解码后的路径名表示形式,以确保加载器数据和元数据解析到同一个静态路由。

路由接线

import { createFileRoute, notFound } from "@tanstack/react-router";
import {
  PageRenderer,
  StartErrorBoundary,
  StartLoading,
  StartNotFound,
} from "@json-render/tanstack-start";
import { getHead, getPageData } from "@/lib/json-app";

export const Route = createFileRoute("/$")({
  loader: async ({ location }) => {
    const data = await getPageData({ pathname: location.pathname });
    if (!data) throw notFound();
    return data;
  },
  head: ({ match }) => getHead({ pathname: match.pathname }),
  component: () => <PageRenderer {...Route.useLoaderData()} />,
  pendingComponent: StartLoading,
  errorComponent: StartErrorBoundary,
  notFoundComponent: StartNotFound,
});

TanStack Router 加载器会在服务器端和客户端运行。如果规范工厂或命名加载器使用凭据、数据库客户端或仅限服务器端的导入,请将 getPageData 和 getHead 包装在 TanStack Start createServerFn 中;不要将该服务器端代码直接导入同构路由加载器。

根 Provider

使用 StartAppProvider 包装根路由的 Outlet。渲染 HeadContent,使 getHead 中的元数据写入文档。

import {
  createRootRoute,
  HeadContent,
  Outlet,
  Scripts,
} from "@tanstack/react-router";
import { StartAppProvider } from "@json-render/tanstack-start";
import { spec } from "@/lib/spec";

export const Route = createRootRoute({
  component: () => (
    <html lang="en">
      <head>
        <HeadContent />
      </head>
      <body>
        <StartAppProvider
          registry={registry}
          handlers={handlers}
          spec={spec}
        >
          <Outlet />
        </StartAppProvider>
        <Scripts />
      </body>
    </html>
  ),
});

将 StartLoading、StartErrorBoundary 和 StartNotFound 用作 TanStack Router 的 pendingComponent、errorComponent 和 notFoundComponent 选项。StartAppProvider 接收 spec 时,每个组件都会选择匹配路由对应的回退组件。显式回退属性会覆盖该查找结果。通过 StartAppProvider.functions 传入命名的 $computed 实现。默认错误边界会使路由器缓存失效,并在用户选择重试时重新运行失败的加载器。

从 @json-render/tanstack-start 导入 React 组件。从 @json-render/tanstack-start/server 导入 schema、createStartApp、matchRoute、resolveMetadata 和静态路径辅助函数。

评论

支持 Markdown