服务器端渲染
非官方测试版翻译
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
要在应用中实现 SSR,只需在 _app.tsx 中设置 ssr: true,但还需要注意以下额外事项。
为了在服务器端渲染阶段正确执行查询并自定义缓存行为,我们可能需要在 _app.tsx 中添加额外逻辑:
pages/_app.tsxtsximport { 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 requestsreturn {transformer: superjson, // optional - adds superjson serializationurl: '/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 serializationurl,/*** 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" headerconst {// eslint-disable-next-line @typescript-eslint/no-unused-varsconnection: _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.tsxtsximport { 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 requestsreturn {transformer: superjson, // optional - adds superjson serializationurl: '/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 serializationurl,/*** 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" headerconst {// eslint-disable-next-line @typescript-eslint/no-unused-varsconnection: _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 助手 在 getStaticProps 或 getServerSideProps 中预取查询。