Renderizado del lado del servidor
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Para habilitar SSR simplemente configura ssr: true en el callback de configuración de tu createTRPCNext.
Cuando habilitas SSR, tRPC usará getInitialProps para precargar todas las consultas en el servidor. Esto genera problemas como este cuando usas getServerSideProps, y resolverlo está fuera de nuestro alcance.
Alternativamente, puedes dejar SSR deshabilitado (valor predeterminado) y usar Helpers del lado del servidor para precargar consultas en getStaticProps o getServerSideProps.
Para ejecutar correctamente las consultas durante la etapa de renderizado del lado del servidor, debemos agregar lógica adicional dentro de nuestro config:
Adicionalmente, considera implementar Response Caching.
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 {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [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: true,});
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 {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [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: true,});
O, si quieres aplicar SSR condicionalmente según una solicitud específica, puedes pasar un callback a ssr. Este callback puede devolver un booleano o una Promesa que resuelva en booleano:
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 {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [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 {transformer: superjson, // optional - adds superjson serializationlinks: [httpBatchLink({url: '/api/trpc',}),],};}return {transformer: superjson, // optional - adds superjson serializationlinks: [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);
Preguntas frecuentes
P: ¿Por qué debo reenviar manualmente los headers del cliente al servidor? ¿Por qué tRPC no lo hace automáticamente?
Aunque es raro que no quieras reenviar los headers del cliente al servidor al usar SSR, podrías necesitar agregar elementos dinámicamente en los headers. Por lo tanto, tRPC no quiere asumir la responsabilidad por posibles colisiones de claves en headers, etc.
P: ¿Por qué necesito eliminar el header connection al usar SSR en Node 18?
Si no eliminas el header connection, la obtención de datos fallará con TRPCClientError: fetch failed porque connection es un nombre de header prohibido.
P: ¿Por qué sigo viendo solicitudes de red en la pestaña Network?
Por defecto, @tanstack/react-query (que usamos para los hooks de obtención de datos) vuelve a buscar datos al montar y al enfocar la ventana, incluso si ya tiene datos iniciales mediante SSR. Esto garantiza que los datos estén siempre actualizados. Consulta la página sobre SSG si deseas deshabilitar este comportamiento.