静的サイト生成
非公式ベータ版翻訳
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
ヒント
静的サイト生成では、各ページの getStaticProps 内で tRPC クエリを実行する必要があります。
これを実現するには、サーバーサイドヘルパーを使用してクエリをプリフェッチし、脱水処理(dehydrate)してページに渡します。クエリは自動的に trpcState を検知し、初期値として使用します。
getStaticProps でのデータ取得
pages/posts/[id].tsxtsximport { createServerSideHelpers } from '@trpc/react-query/server';import {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import { prisma } from 'server/context';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';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 {GetStaticPaths,GetStaticPropsContext,InferGetStaticPropsType,} from 'next';import { prisma } from 'server/context';import { appRouter } from 'server/routers/_app';import superjson from 'superjson';import { trpc } from 'utils/trpc';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 {transformer: superjson,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 {transformer: superjson,links: [httpBatchLink({url: `${getBaseUrl()}/api/trpc`,}),],// Change options globallyqueryClientConfig: {defaultOptions: {queries: {refetchOnMount: false,refetchOnWindowFocus: false,},},},},},});
アプリケーションで静的クエリと動的クエリが混在する場合、この設定方法には注意が必要です。