服务端渲染
非官方测试版翻译
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
只需在 createTRPCNext 配置回调中设置 ssr: true 即可启用 SSR。
信息
为了在服务端渲染阶段正确执行查询,我们需要在 config 中添加额外逻辑:
此外,考虑Response Caching。
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import { ssrPrepass } from '@trpc/next/ssrPrepass';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({ssr: true,ssrPrepass,config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import { ssrPrepass } from '@trpc/next/ssrPrepass';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({ssr: true,ssrPrepass,config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},});
或者,若需根据特定请求条件启用 SSR,可向 ssr 传递回调函数。此回调可返回布尔值,或解析为布尔值的 Promise:
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
常见问题
问:为什么需要手动将客户端 headers 转发到服务器?tRPC 不能自动处理吗?
虽然在 SSR 场景中通常都需要转发客户端 headers,但您可能需要在 headers 中动态添加内容。因此 tRPC 不负责处理 header 键名冲突等问题。
问:为什么在 Node 18 上使用 SSR 时需要删除 connection 头?
若不移除 connection 头,数据获取将失败并出现 TRPCClientError: fetch failed 错误,因为 connection 属于禁用标头名称。
问:为什么在 Network 标签页仍能看到网络请求?
默认情况下,@tanstack/react-query(我们用于数据获取的 hooks)会在组件挂载和窗口重新聚焦时重新获取数据,即使已通过 SSR 获得初始数据。这确保了数据始终最新。如需禁用此行为,请参阅静态站点生成(SSG)页面。