Aller au contenu principal
Version : 11.x

Mise en cache des réponses

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 →

Comme toutes les requêtes tRPC sont des requêtes HTTP GET normales, vous pouvez utiliser les en-têtes de cache HTTP standard pour mettre les réponses en cache. Cela permet d'obtenir des réponses rapides, de soulager votre base de données et d'aider à faire évoluer votre API.

info

Soyez toujours prudent avec la mise en cache, en particulier si vous traitez des informations personnelles.

  Comme le regroupement par lot est activé par défaut, il est recommandé de définir vos en-têtes de cache dans la fonction responseMeta et de vous assurer qu'il n'y a aucun appel concurrent pouvant contenir des données personnelles - ou d'omettre complètement les en-têtes de cache s'il existe un en-tête d'authentification ou un cookie.

  Vous pouvez également utiliser un splitLink pour séparer vos requêtes publiques de celles qui doivent rester privées et non mises en cache.

Utilisation de responseMeta pour mettre les réponses en cache

La plupart des adaptateurs tRPC prennent en charge un callback responseMeta qui vous permet de définir des en-têtes HTTP (y compris les en-têtes de cache) en fonction des procédures appelées.

Cela fonctionne avec tout fournisseur d'hébergement prenant en charge les en-têtes de cache HTTP standard (par exemple Vercel, Cloudflare, AWS CloudFront).

server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
 
export const createContext = async (opts: CreateHTTPContextOptions) => {
return {
req: opts.req,
res: opts.res,
};
};
 
type Context = Awaited<ReturnType<typeof createContext>>;
 
export const t = initTRPC.context<Context>().create();
 
const waitFor = async (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));
 
export const appRouter = t.router({
public: t.router({
slowQueryCached: t.procedure.query(async (opts) => {
await waitFor(5000); // wait for 5s
 
return {
lastUpdated: new Date().toJSON(),
};
}),
}),
});
 
// Exporting `type AppRouter` only exposes types that can be used for inference
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
export type AppRouter = typeof appRouter;
 
// export API handler
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta(opts) {
const { paths, errors, type } = opts;
// assuming you have all your public routes with the keyword `public` in them
const allPublic = paths && paths.every((path) => path.includes('public'));
// checking that no procedures errored
const allOk = errors.length === 0;
// checking we're doing a query request
const isQuery = type === 'query';
 
if (allPublic && allOk && isQuery) {
// cache request for 1 day + revalidate once every second
const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
return {
headers: new Headers([
[
'cache-control',
`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,
],
]),
};
}
return {};
},
});
 
server.listen(3000);
server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import type { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
 
export const createContext = async (opts: CreateHTTPContextOptions) => {
return {
req: opts.req,
res: opts.res,
};
};
 
type Context = Awaited<ReturnType<typeof createContext>>;
 
export const t = initTRPC.context<Context>().create();
 
const waitFor = async (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));
 
export const appRouter = t.router({
public: t.router({
slowQueryCached: t.procedure.query(async (opts) => {
await waitFor(5000); // wait for 5s
 
return {
lastUpdated: new Date().toJSON(),
};
}),
}),
});
 
// Exporting `type AppRouter` only exposes types that can be used for inference
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
export type AppRouter = typeof appRouter;
 
// export API handler
const server = createHTTPServer({
router: appRouter,
createContext,
responseMeta(opts) {
const { paths, errors, type } = opts;
// assuming you have all your public routes with the keyword `public` in them
const allPublic = paths && paths.every((path) => path.includes('public'));
// checking that no procedures errored
const allOk = errors.length === 0;
// checking we're doing a query request
const isQuery = type === 'query';
 
if (allPublic && allOk && isQuery) {
// cache request for 1 day + revalidate once every second
const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
return {
headers: new Headers([
[
'cache-control',
`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,
],
]),
};
}
return {};
},
});
 
server.listen(3000);
astuce

Si vous utilisez Next.js, consultez le guide de mise en cache SSR de Next.js pour des exemples spécifiques à Next.js utilisant createTRPCNext et l'adaptateur Next.js.