Generación de Sitios Estáticos
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Proyecto de referencia: https://github.com/trpc/examples-next-prisma-todomvc
La generación de sitios estáticos requiere ejecutar consultas tRPC dentro de getStaticProps en cada página.
Esto se logra usando ayudantes del lado del servidor para prefetch de consultas, deshidratarlas y pasarlas a la página. Las consultas luego detectarán automáticamente el estado trpcState y lo usarán como valor inicial.
Obtener datos en getStaticProps
pages/posts/[id].tsxtsximport { createServerSideHelpers } from '@trpc/react-query/server';import { prisma } from '~/server/context';import { appRouter } from '~/server/routers/_app';import { trpc } from '~/utils/trpc';import {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import superjson from 'superjson';export async function getStaticProps(context: GetStaticPropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson, // optional - adds superjson serialization});const id = context.params?.id as string;// prefetch `post.byId`await helpers.post.byId.prefetch({ id });return {props: {trpcState: helpers.dehydrate(),id,},revalidate: 1,};}export const getStaticPaths: GetStaticPaths = async () => {const posts = await prisma.post.findMany({select: {id: true,},});return {paths: posts.map((post) => ({params: {id: post.id,},})),// https://nextjs.org/docs/pages/api-reference/functions/get-static-paths#fallback-blockingfallback: 'blocking',};};export default function PostViewPage(props: InferGetStaticPropsType<typeof getStaticProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since we're using `fallback: "blocking"`return <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString('en-us')}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}
pages/posts/[id].tsxtsximport { createServerSideHelpers } from '@trpc/react-query/server';import { prisma } from '~/server/context';import { appRouter } from '~/server/routers/_app';import { trpc } from '~/utils/trpc';import {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import superjson from 'superjson';export async function getStaticProps(context: GetStaticPropsContext<{ id: string }>,) {const helpers = createServerSideHelpers({router: appRouter,ctx: {},transformer: superjson, // optional - adds superjson serialization});const id = context.params?.id as string;// prefetch `post.byId`await helpers.post.byId.prefetch({ id });return {props: {trpcState: helpers.dehydrate(),id,},revalidate: 1,};}export const getStaticPaths: GetStaticPaths = async () => {const posts = await prisma.post.findMany({select: {id: true,},});return {paths: posts.map((post) => ({params: {id: post.id,},})),// https://nextjs.org/docs/pages/api-reference/functions/get-static-paths#fallback-blockingfallback: 'blocking',};};export default function PostViewPage(props: InferGetStaticPropsType<typeof getStaticProps>,) {const { id } = props;const postQuery = trpc.post.byId.useQuery({ id });if (postQuery.status !== 'success') {// won't happen since we're using `fallback: "blocking"`return <>Loading...</>;}const { data } = postQuery;return (<><h1>{data.title}</h1><em>Created {data.createdAt.toLocaleDateString('en-us')}</em><p>{data.text}</p><h2>Raw data:</h2><pre>{JSON.stringify(data, null, 4)}</pre></>);}
Ten en cuenta que el comportamiento predeterminado de react-query es reobtener los datos en el cliente al montarse. Si quieres obtener los datos exclusivamente mediante getStaticProps, debes configurar refetchOnMount y refetchOnWindowFocus como false en las opciones de consulta.
Esto puede ser preferible para minimizar solicitudes a tu API, especialmente útil si usas APIs de terceros con límites de tasa.
Se puede configurar por consulta individual:
tsxconst data = trpc.example.useQuery(// if your query takes no input, make sure that you don't// accidentally pass the query options as the first argumentundefined,{ refetchOnMount: false, refetchOnWindowFocus: false },);
tsxconst data = trpc.example.useQuery(// if your query takes no input, make sure that you don't// accidentally pass the query options as the first argumentundefined,{ refetchOnMount: false, refetchOnWindowFocus: false },);
O globalmente, si todas las consultas de tu aplicación deben comportarse igual:
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) {return {links: [httpBatchLink({url: `${getBaseUrl()}/api/trpc`,}),],// Change options globallyqueryClientConfig: {defaultOptions: {queries: {refetchOnMount: false,refetchOnWindowFocus: false,},},},},},});
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) {return {links: [httpBatchLink({url: `${getBaseUrl()}/api/trpc`,}),],// Change options globallyqueryClientConfig: {defaultOptions: {queries: {refetchOnMount: false,refetchOnWindowFocus: false,},},},},},});
Ten cuidado con este enfoque si tu aplicación mezcla consultas estáticas y dinámicas.