Hoppa till huvudinnehållet
Version: 10.x

Server-side rendering

Inofficiell Beta-översättning

Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →

För att aktivera SSR behöver du bara sätta ssr: true i din createTRPCNext-konfigurationscallback.

info

När du aktiverar SSR kommer tRPC att använda getInitialProps för att förhämtra alla queries på servern. Detta leder till problem som detta när du använder getServerSideProps, och att lösa detta ligger utanför vår kontroll.

 
Alternativt kan du lämna SSR inaktiverat (standardinställningen) och använda Server-Side Helpers för att förhämta queries i getStaticProps eller getServerSideProps.

För att köra queries korrekt under server-side rendering behöver vi lägga till extra logik i vår config:

Överväg dessutom att använda Response Caching.

utils/trpc.ts
tsx
import { 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 requests
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
url: '/api/trpc',
}),
],
};
}
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
// The server needs to know your app's full url
url: `${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 rendering
return {
cookie: ctx.req.headers.cookie,
};
},
}),
],
};
},
ssr: true,
});
utils/trpc.ts
tsx
import { 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 requests
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
url: '/api/trpc',
}),
],
};
}
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
// The server needs to know your app's full url
url: `${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 rendering
return {
cookie: ctx.req.headers.cookie,
};
},
}),
],
};
},
ssr: true,
});

eller, om du vill aktivera SSR villkorligt baserat på en specifik förfrågan, kan du skicka en callback till ssr. Denna callback kan returnera ett booleskt värde eller ett Promise som resolver till ett booleskt värde:

utils/trpc.ts
tsx
import { 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 requests
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
url: '/api/trpc',
}),
],
};
}
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
// The server needs to know your app's full url
url: `${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 rendering
return {
cookie: ctx.req.headers.cookie,
};
},
}),
],
};
},
ssr(opts) {
// only SSR if the request is coming from a bot
return opts.ctx?.req?.headers['user-agent']?.includes('bot');
},
});
utils/trpc.ts
tsx
import { 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 requests
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
url: '/api/trpc',
}),
],
};
}
return {
transformer: superjson, // optional - adds superjson serialization
links: [
httpBatchLink({
// The server needs to know your app's full url
url: `${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 rendering
return {
cookie: ctx.req.headers.cookie,
};
},
}),
],
};
},
ssr(opts) {
// only SSR if the request is coming from a bot
return opts.ctx?.req?.headers['user-agent']?.includes('bot');
},
});
pages/_app.tsx
tsx
import { 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.tsx
tsx
import { 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);

Vanliga frågor

F: Varför måste jag vidarebefordra klientens headers till servern manuellt? Varför gör inte tRPC detta automatiskt?

Även om det är ovanligt att man inte vill vidarebefordra klientens headers till servern vid SSR, kan du vilja lägga till saker dynamiskt i headern. Därför vill tRPC inte ta ansvar för potentiella kollisioner av header-nycklar etc.

F: Varför måste jag ta bort connection-headern när jag använder SSR på Node 18?

Om du inte tar bort connection-headern kommer datahämtningen att misslyckas med TRPCClientError: fetch failed eftersom connection är ett förbjudet headernamn.

F: Varför ser jag fortfarande nätverksförfrågorna i Network-fliken?

Som standard kommer @tanstack/react-query (som vi använder för datahämtningshooks) att hämta data igen vid mount och fönsterfokusering, även om den redan har initialdata via SSR. Detta säkerställer att data alltid är aktuell. Se sidan om SSG om du vill inaktivera detta beteende.