伺服器端輔助
伺服器端輔助提供一組輔助函式,可讓您在伺服器上預先擷取查詢。這對 SSG 有用,但如果您選擇不使用 ssr: true
,對 SSR 也有用。
透過伺服器端輔助預先擷取可讓查詢快取在伺服器上填入,這表示這些查詢最初不必在前端擷取。
有 2 種方法可以使用伺服器端輔助。
1. 內部路由器
當您有權限存取 tRPC 路由器時,會使用此方法。例如,在開發單體 Next.js 應用程式時。
使用輔助程式可讓 tRPC 直接在伺服器上呼叫你的程序,無需 HTTP 要求,類似於伺服器端呼叫。這也表示你沒有像平常一樣手邊有要求和回應。請務必使用不含 req
和 res
的內容建立伺服器端輔助程式,這些內容通常會透過內容建立填入。我們建議在這種情況下採用"內部" 和 "外部" 內容的概念。
ts
import { createServerSideHelpers } from '@trpc/react-query/server';import { createContext } from '~/server/context';import superjson from 'superjson';const helpers = createServerSideHelpers({router: appRouter,ctx: await createContext(),transformer: superjson, // optional - adds superjson serialization});
ts
import { createServerSideHelpers } from '@trpc/react-query/server';import { createContext } from '~/server/context';import superjson from 'superjson';const helpers = createServerSideHelpers({router: appRouter,ctx: await createContext(),transformer: superjson, // optional - adds superjson serialization});
2. 外部路由器
當你無法直接存取你的 tRPC 路由器時,就會使用此方法。例如,在開發 Next.js 應用程式和獨立 API 分別主機時。
ts
import { createTRPCClient } from '@trpc/client';import { createServerSideHelpers } from '@trpc/react-query/server';import superjson from 'superjson';const proxyClient = createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:3000/api/trpc',}),],});const helpers = createServerSideHelpers({client: proxyClient,});
ts
import { createTRPCClient } from '@trpc/client';import { createServerSideHelpers } from '@trpc/react-query/server';import superjson from 'superjson';const proxyClient = createTRPCClient<AppRouter>({links: [httpBatchLink({url: 'http://localhost:3000/api/trpc',}),],});const helpers = createServerSideHelpers({client: proxyClient,});
輔助程式使用
伺服器端輔助程式方法會傳回一個物件,很像 tRPC 客戶端,其中包含你的所有路由器作為金鑰。不過,你會取得 prefetch
、fetch
、prefetchInfinite
和 fetchInfinite
函式,而不是 useQuery
和 useMutation
。
prefetch
和 fetch
之間的主要差異在於,fetch
的作用很像一般函式呼叫,傳回查詢的結果,而 prefetch
既不會傳回結果,也不會引發例外 - 如果你需要這種行為,請改用 fetch
。相反地,prefetch
會將查詢新增到快取中,你會先將其脫水,然後傳送到客戶端。
ts
return {props: {// very important - use `trpcState` as the keytrpcState: helpers.dehydrate(),},};
ts
return {props: {// very important - use `trpcState` as the keytrpcState: helpers.dehydrate(),},};
經驗法則為,對於你已知在客戶端會需要的查詢,請使用 prefetch
,而對於你想要在伺服器上使用其結果的查詢,請使用 fetch
。
這些函式都是 react-query 函式的包裝器。請查看其文件,以詳細瞭解它們。
如需完整範例,請參閱我們的E2E SSG 測試範例
Next.js 範例
pages/posts/[id].tsxtsx
import { createServerSideHelpers } from '@trpc/react-query/server';import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';export async function getServerSideProps(context: GetServerSidePropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson,});const id = context.params?.id as string;/** Prefetching the `post.byId` query.* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.*/await helpers.post.byId.prefetch({ id });// Make sure to return { props: { trpcState: helpers.dehydrate() } }return {props: {trpcState: helpers.dehydrate(),id,},};}export default function PostViewPage(props: InferGetServerSidePropsType<typeof getServerSideProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since the query has been prefetchedreturn <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString()}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}
pages/posts/[id].tsxtsx
import { createServerSideHelpers } from '@trpc/react-query/server';import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';export async function getServerSideProps(context: GetServerSidePropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson,});const id = context.params?.id as string;/** Prefetching the `post.byId` query.* `prefetch` does not return the result and never throws - if you need that behavior, use `fetch` instead.*/await helpers.post.byId.prefetch({ id });// Make sure to return { props: { trpcState: helpers.dehydrate() } }return {props: {trpcState: helpers.dehydrate(),id,},};}export default function PostViewPage(props: InferGetServerSidePropsType<typeof getServerSideProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since the query has been prefetchedreturn <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString()}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}