Aller au contenu principal
Version : 10.x

Génération de site statique

Traduction Bêta Non Officielle

Cette page a été traduite par PageTurner AI (bêta). Non approuvée officiellement par le projet. Vous avez trouvé une erreur ? Signaler un problème →

La génération de site statique nécessite d'exécuter les requêtes tRPC dans getStaticProps sur chaque page.

Ceci peut être réalisé en utilisant les aides côté serveur pour précharger les requêtes, les déshydrater et les transmettre à la page. Les requêtes récupéreront alors automatiquement le trpcState et l'utiliseront comme valeur initiale.

Récupérer les données dans getStaticProps

pages/posts/[id].tsx
tsx
import { 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-blocking
fallback: '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].tsx
tsx
import { 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-blocking
fallback: '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>
</>
);
}

Notez que le comportement par défaut de react-query est de recharger les données côté client lors du montage. Si vous souhaitez uniquement récupérer les données via getStaticProps, vous devez définir refetchOnMount et refetchOnWindowFocus sur false dans les options de requête.

Cette approche est préférable pour minimiser le nombre de requêtes vers votre API, ce qui peut s'avérer nécessaire avec une API tierce limitée en débit par exemple.

Ce réglage peut s'appliquer par requête :

tsx
const data = trpc.example.useQuery(
// if your query takes no input, make sure that you don't
// accidentally pass the query options as the first argument
undefined,
{ refetchOnMount: false, refetchOnWindowFocus: false },
);
tsx
const data = trpc.example.useQuery(
// if your query takes no input, make sure that you don't
// accidentally pass the query options as the first argument
undefined,
{ refetchOnMount: false, refetchOnWindowFocus: false },
);

Ou globalement si toutes les requêtes de votre application doivent adopter le même comportement :

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) {
return {
transformer: superjson,
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
// Change options globally
queryClientConfig: {
defaultOptions: {
queries: {
refetchOnMount: false,
refetchOnWindowFocus: false,
},
},
},
},
},
});
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) {
return {
transformer: superjson,
links: [
httpBatchLink({
url: `${getBaseUrl()}/api/trpc`,
}),
],
// Change options globally
queryClientConfig: {
defaultOptions: {
queries: {
refetchOnMount: false,
refetchOnWindowFocus: false,
},
},
},
},
},
});

Soyez vigilant avec cette méthode si votre application combine des requêtes statiques et dynamiques.