跳至主内容
版本:9.x

服务器端渲染

非官方测试版翻译

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

要在应用中实现 SSR,只需在 _app.tsx 中设置 ssr: true,但还需要注意以下额外事项。

为了在服务器端渲染阶段正确执行查询并自定义缓存行为,我们可能需要在 _app.tsx 中添加额外逻辑:

pages/_app.tsx
tsx
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import React from 'react';
import superjson from 'superjson';
import type { AppRouter } from './api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config(config) {
if (typeof window !== 'undefined') {
// during client requests
return {
transformer: superjson, // optional - adds superjson serialization
url: '/api/trpc',
};
}
// during SSR below
// optional: use SSG-caching for each rendered page (see caching section for more details)
const ONE_DAY_SECONDS = 60 * 60 * 24;
ctx?.res?.setHeader(
'Cache-Control',
`s-maxage=1, stale-while-revalidate=${ONE_DAY_SECONDS}`,
);
// The server needs to know your app's full url
// On render.com you can use `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}/api/trpc`
const url = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}/api/trpc`
: 'http://localhost:3000/api/trpc';
return {
transformer: superjson, // optional - adds superjson serialization
url,
/**
* Set custom request headers on every request from tRPC
* @see http://localhost:3000/docs/v9/header
* @see http://localhost:3000/docs/v9/ssr
*/
headers() {
if (ctx?.req) {
// To use SSR properly, you need to forward the client's headers to the server
// This is so you can pass through things like cookies when we're server-side rendering
// If you're using Node 18, omit the "connection" header
const {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
connection: _connection,
...headers
} = ctx.req.headers;
return {
...headers,
// Optional: inform server that it's an SSR request
'x-ssr': '1',
};
}
return {};
},
};
},
ssr: true,
})(MyApp);
pages/_app.tsx
tsx
import { withTRPC } from '@trpc/next';
import { AppType } from 'next/dist/shared/lib/utils';
import React from 'react';
import superjson from 'superjson';
import type { AppRouter } from './api/trpc/[trpc]';
const MyApp: AppType = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
};
export default withTRPC<AppRouter>({
config(config) {
if (typeof window !== 'undefined') {
// during client requests
return {
transformer: superjson, // optional - adds superjson serialization
url: '/api/trpc',
};
}
// during SSR below
// optional: use SSG-caching for each rendered page (see caching section for more details)
const ONE_DAY_SECONDS = 60 * 60 * 24;
ctx?.res?.setHeader(
'Cache-Control',
`s-maxage=1, stale-while-revalidate=${ONE_DAY_SECONDS}`,
);
// The server needs to know your app's full url
// On render.com you can use `http://${process.env.RENDER_INTERNAL_HOSTNAME}:${process.env.PORT}/api/trpc`
const url = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}/api/trpc`
: 'http://localhost:3000/api/trpc';
return {
transformer: superjson, // optional - adds superjson serialization
url,
/**
* Set custom request headers on every request from tRPC
* @see http://localhost:3000/docs/v9/header
* @see http://localhost:3000/docs/v9/ssr
*/
headers() {
if (ctx?.req) {
// To use SSR properly, you need to forward the client's headers to the server
// This is so you can pass through things like cookies when we're server-side rendering
// If you're using Node 18, omit the "connection" header
const {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
connection: _connection,
...headers
} = ctx.req.headers;
return {
...headers,
// Optional: inform server that it's an SSR request
'x-ssr': '1',
};
}
return {};
},
};
},
ssr: true,
})(MyApp);

常见问题

问:为什么需要手动将客户端 headers 转发到服务器?tRPC 不能自动处理吗?

虽然在 SSR 场景中通常都需要转发客户端 headers,但您可能需要在 headers 中动态添加内容。因此 tRPC 不负责处理 header 键名冲突等问题。

问:为什么在 Node 18 上使用 SSR 时需要删除 connection 头?

若不移除 connection 头,数据获取将失败并出现 TRPCClientError: fetch failed 错误,因为 connection 属于禁用标头名称

问:使用 SSR 时还能同时使用 getServerSideProps 和/或 getStaticProps 吗?

启用 SSR 时,tRPC 会通过 getInitialProps 在服务端预取所有查询。当您在页面中使用 getServerSideProps 时,这会导致此类问题,且该问题超出我们的解决范围。不过您可以使用 SSG 助手getStaticPropsgetServerSideProps 中预取查询。