정적 사이트 생성
비공식 베타 번역
이 페이지는 PageTurner AI로 번역되었습니다(베타). 프로젝트 공식 승인을 받지 않았습니다. 오류를 발견하셨나요? 문제 신고 →
정적 사이트 생성은 각 페이지의 getStaticProps 내부에서 tRPC 쿼리를 실행해야 합니다.
서버 사이드 헬퍼를 사용하여 쿼리를 미리 가져오고, dehydrate한 다음 페이지로 전달하면 됩니다. 그러면 쿼리가 자동으로 trpcState를 가져와 초기값으로 사용합니다.
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></>);}
react-query의 기본 동작은 마운트 시 클라이언트 사이드에서 데이터를 다시 가져오는 것이므로, getStaticProps를 통해서만 데이터를 가져오고 싶다면 쿼리 옵션에서 refetchOnMount와 refetchOnWindowFocus를 false로 설정해야 합니다.
이는 API 요청 수를 최소화하고 싶을 때 유용하며, 예를 들어 요청량이 제한된 서드파티 API를 사용하는 경우 필요할 수 있습니다.
쿼리별로 설정할 수 있습니다:
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 },);
애플리케이션 전체의 모든 쿼리가 동일하게 동작해야 한다면 전역적으로 설정할 수도 있습니다:
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,},},},},},});
애플리케이션에 정적 쿼리와 동적 쿼리가 혼합되어 있다면 이 방식 사용 시 주의가 필요합니다.