跳至主内容
版本:11.x

在 Next.js Pages Router 中配置 tRPC

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

注意

本指南适用于 Next.js Pages Router。若您使用 Next.js App Router,请参阅 App Router 配置指南

推荐文件结构

我们推荐采用如下文件结构,尽管 tRPC 并不强制要求。这正是示例项目中采用的结构,本文后续内容将逐步指导你如何在该结构中集成 tRPC。

graphql
.
├── prisma # <-- if prisma is added
│ └── [..]
├── src
│ ├── pages
│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here
│ │ ├── api
│ │ │ └── trpc
│ │ │ └── [trpc].ts # <-- tRPC HTTP handler
│ │ └── [..]
│ ├── server
│ │ ├── routers
│ │ │ ├── _app.ts # <-- main app router
│ │ │ ├── post.ts # <-- sub routers
│ │ │ └── [..]
│ │ ├── context.ts # <-- create app context
│ │ └── trpc.ts # <-- procedure helpers
│ └── utils
│ └── trpc.ts # <-- your typesafe tRPC hooks
└── [..]
graphql
.
├── prisma # <-- if prisma is added
│ └── [..]
├── src
│ ├── pages
│ │ ├── _app.tsx # <-- add `withTRPC()`-HOC here
│ │ ├── api
│ │ │ └── trpc
│ │ │ └── [trpc].ts # <-- tRPC HTTP handler
│ │ └── [..]
│ ├── server
│ │ ├── routers
│ │ │ ├── _app.ts # <-- main app router
│ │ │ ├── post.ts # <-- sub routers
│ │ │ └── [..]
│ │ ├── context.ts # <-- create app context
│ │ └── trpc.ts # <-- procedure helpers
│ └── utils
│ └── trpc.ts # <-- your typesafe tRPC hooks
└── [..]

在现有 Next.js 项目中集成 tRPC

1. 安装依赖

npm install @trpc/server @trpc/client @trpc/react-query @trpc/next @tanstack/react-query@latest zod
AI 代理

若您使用 AI 编程代理,请安装 tRPC 技能以优化代码生成效果:

bash
npx @tanstack/intent@latest install
bash
npx @tanstack/intent@latest install

Next.js 集成方案本质上是 React Query 集成与 Next.js 特定功能的组合实现。

2. 启用严格模式

若使用 Zod 进行输入验证,需在 tsconfig.json 中启用严格模式:

tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strict": true
}

如果严格模式限制过强,你至少需要启用 strictNullChecks

tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}
tsconfig.json
diff
"compilerOptions": {
+ "strictNullChecks": true
}

3. 创建 tRPC 路由

src/server/trpc.ts 中使用 initTRPC 函数初始化 tRPC 后端,并创建你的第一个路由器。我们将在此创建一个简单的 "hello world" 路由器和过程 - 关于创建 tRPC API 的深入信息,请参考:

View sample backend
server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
// Avoid exporting the entire t-object
// since it's not very descriptive.
// For instance, the use of a t variable
// is common in i18n libraries.
const t = initTRPC.create();
 
// Base router and procedure helpers
export const router = t.router;
export const procedure = t.procedure;
server/trpc.ts
ts
import { initTRPC } from '@trpc/server';
 
// Avoid exporting the entire t-object
// since it's not very descriptive.
// For instance, the use of a t variable
// is common in i18n libraries.
const t = initTRPC.create();
 
// Base router and procedure helpers
export const router = t.router;
export const procedure = t.procedure;

server/routers/_app.ts
ts
import { z } from 'zod';
import { procedure, router } from '../trpc';
 
export const appRouter = router({
hello: procedure
.input(
z.object({
text: z.string(),
}),
)
.query((opts) => {
return {
greeting: `hello ${opts.input.text}`,
};
}),
});
 
// export type definition of API
export type AppRouter = typeof appRouter;
server/routers/_app.ts
ts
import { z } from 'zod';
import { procedure, router } from '../trpc';
 
export const appRouter = router({
hello: procedure
.input(
z.object({
text: z.string(),
}),
)
.query((opts) => {
return {
greeting: `hello ${opts.input.text}`,
};
}),
});
 
// export type definition of API
export type AppRouter = typeof appRouter;

pages/api/trpc/[trpc].ts
ts
import * as trpcNext from '@trpc/server/adapters/next';
import { appRouter } from '../../../server/routers/_app';
 
// export API handler
// @link https://trpc.io/docs/server/adapters
export default trpcNext.createNextApiHandler({
router: appRouter,
createContext: () => ({}),
});
pages/api/trpc/[trpc].ts
ts
import * as trpcNext from '@trpc/server/adapters/next';
import { appRouter } from '../../../server/routers/_app';
 
// export API handler
// @link https://trpc.io/docs/server/adapters
export default trpcNext.createNextApiHandler({
router: appRouter,
createContext: () => ({}),
});
备注

上述后端使用了推荐的文件结构,但你也可以简化处理,将所有内容直接放入 API 处理程序

4. 创建 tRPC 钩子

使用 createTRPCNext 函数,根据 API 类型签名创建强类型的 React Hook 集合。

utils/trpc.ts
tsx
import { httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
 
function getBaseUrl() {
if (typeof window !== 'undefined')
// browser should use relative path
return '';
 
if (process.env.VERCEL_URL)
// reference for vercel.com
return `https://${process.env.VERCEL_URL}`;
 
if (process.env.RENDER_INTERNAL_HOSTNAME)
// reference for render.com
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
 
// assume localhost
return `http://localhost:${process.env.PORT ?? 3000}`;
}
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
httpBatchLink({
/**
* If you want to use SSR, you need to use the server's full URL
* @see https://trpc.io/docs/client/nextjs/pages-router/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
 
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/client/nextjs/pages-router/ssr
**/
ssr: false,
});
utils/trpc.ts
tsx
import { httpBatchLink } from '@trpc/client';
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
 
function getBaseUrl() {
if (typeof window !== 'undefined')
// browser should use relative path
return '';
 
if (process.env.VERCEL_URL)
// reference for vercel.com
return `https://${process.env.VERCEL_URL}`;
 
if (process.env.RENDER_INTERNAL_HOSTNAME)
// reference for render.com
return `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}`;
 
// assume localhost
return `http://localhost:${process.env.PORT ?? 3000}`;
}
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
httpBatchLink({
/**
* If you want to use SSR, you need to use the server's full URL
* @see https://trpc.io/docs/client/nextjs/pages-router/ssr
**/
url: `${getBaseUrl()}/api/trpc`,
 
// You can pass any HTTP headers you wish here
async headers() {
return {
// authorization: getAuthCookie(),
};
},
}),
],
};
},
/**
* @see https://trpc.io/docs/client/nextjs/pages-router/ssr
**/
ssr: false,
});
备注

createTRPCNext 不兼容 tRPC v9 的互操作模式。若您正从 v9 迁移且使用互操作功能,请继续采用 旧版初始化方式

5. 配置 _app.tsx

将根应用页面包裹在 trpc.withTRPC 高阶组件中,类似如下:

pages/_app.tsx
tsx
import type { AppType } from 'next/app';
import { trpc } from '../utils/trpc';
 
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
 
export default trpc.withTRPC(MyApp);
pages/_app.tsx
tsx
import type { AppType } from 'next/app';
import { trpc } from '../utils/trpc';
 
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
 
export default trpc.withTRPC(MyApp);

6. 发起 API 请求

全部设置完成!

您现在可以使用刚创建的 React Hook 调用 API 接口。更多细节请参阅 React Query 集成文档

pages/index.tsx
tsx
import { trpc } from '../utils/trpc';
 
export default function IndexPage() {
const hello = trpc.hello.useQuery({ text: 'client' });
if (!hello.data) {
return <div>Loading...</div>;
}
return (
<div>
<p>{hello.data.greeting}</p>
</div>
);
}
pages/index.tsx
tsx
import { trpc } from '../utils/trpc';
 
export default function IndexPage() {
const hello = trpc.hello.useQuery({ text: 'client' });
if (!hello.data) {
return <div>Loading...</div>;
}
return (
<div>
<p>{hello.data.greeting}</p>
</div>
);
}

createTRPCNext() 的选项

config 回调函数

config 参数是一个返回配置对象的函数,该对象用于设置 tRPC 和 React Query 客户端。此函数接收包含可选 ctx 属性(类型为 NextPageContext)的对象,使您能在服务端渲染期间访问 Next.js 的 req 对象。返回值可包含以下属性:

  • 必需

  • links:用于定制 tRPC 客户端与服务器间的数据流。了解更多

  • 可选:

  • queryClientConfig:用于配置 tRPC React 钩子内部使用的 React Query QueryClient 对象:QueryClient 文档

  • queryClient:一个 React Query 的 QueryClient 实例

    • 注意queryClientqueryClientConfig 只能二选一提供
  • transformer: 应用于输出数据的转换器。了解更多关于数据转换器的信息

  • abortOnUnmount: 决定组件卸载时是否取消进行中的请求。默认为 false

overrides:(默认值:undefined)

配置 React Query 钩子的覆盖选项

ssr-布尔值(默认:false

控制 tRPC 在服务端渲染页面时是否等待查询完成,默认值为 false

responseMeta-回调函数

用于在服务端渲染时设置响应头与 HTTP 状态码。

示例

utils/trpc.ts
tsx
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
/* [...] */
],
};
},
});
utils/trpc.ts
tsx
import { createTRPCNext } from '@trpc/next';
import type { AppRouter } from '../server/routers/_app';
 
export const trpc = createTRPCNext<AppRouter>({
config(config) {
return {
links: [
/* [...] */
],
};
},
});

后续步骤

浏览文档其他部分了解更多内容,例如授权机制中间件错误处理

您还可以了解查询变更的相关信息,特别是现在您正在使用 @trpc/react-query