Cachning av svar
Denna sida har översatts av PageTurner AI (beta). Inte officiellt godkänd av projektet. Hittade du ett fel? Rapportera problem →
Exemplen nedan använder Vercels edge-cachning för att servera data till dina användare så snabbt som möjligt.
⚠️ En varning ⚠️
Var alltid försiktig med cachning - särskilt när du hanterar personuppgifter.
Eftersom batchbearbetning är aktiverat som standard rekommenderas det att du sätter dina cache-headers i funktionen responseMeta och ser till att det inte finns samtidiga anrop som kan innehålla personuppgifter - eller att utelämna cache-headers helt om det finns auth-headers eller en cookie.
Du kan också använda en splitLink för att separera dina förfrågningar i publika och privata/icke-cachade.
Appcachning
Om du aktiverar SSR i din app kan du upptäcka att den laddas långsamt på t.ex. Vercel, men du kan faktiskt rendera hela din app statiskt utan SSG; läs den här Twitter-tråden för mer insikter.
Exempelkod
pages/_app.tsxtsxexport default withTRPC({config(config) {if (typeof window !== 'undefined') {return {url: '/api/trpc',};}const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {url,};},ssr: true,responseMeta(config) {if (config.clientErrors.length) {// propagate http first error from API callsreturn {status: config.clientErrors[0].data?.httpStatus ?? 500,};}// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: {'cache-control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,},};},})(MyApp);
pages/_app.tsxtsxexport default withTRPC({config(config) {if (typeof window !== 'undefined') {return {url: '/api/trpc',};}const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {url,};},ssr: true,responseMeta(config) {if (config.clientErrors.length) {// propagate http first error from API callsreturn {status: config.clientErrors[0].data?.httpStatus ?? 500,};}// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: {'cache-control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,},};},})(MyApp);
Cachning av API-svar
Eftersom alla frågor är vanliga HTTP GET:ar kan vi använda normala HTTP-headers för att cacha svar, göra svaren blixtsnabb, ge din databas en paus och enklare skala ditt API till otaliga användare.
Använda responseMeta för att cacha svar
Förutsatt att du distribuerar ditt API någonstans som hanterar stale-while-revalidate cache-headers som Vercel.
server.tstsximport * as trpc from '@trpc/server';import { inferAsyncReturnType } from '@trpc/server';import * as trpcNext from '@trpc/server/adapters/next';export const createContext = async ({req,res,}: trpcNext.CreateNextContextOptions) => {return {req,res,prisma,};};type Context = inferAsyncReturnType<typeof createContext>;export function createRouter() {return trpc.router<Context>();}const waitFor = async (ms: number) =>new Promise((resolve) => setTimeout(resolve, ms));export const appRouter = createRouter().query('public.slow-query-cached', {async resolve({ ctx }) {await waitFor(5000); // wait for 5sreturn {lastUpdated: new Date().toJSON(),};},});// Exporting type _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-exportexport type AppRouter = typeof appRouter;// export API handlerexport default trpcNext.createNextApiHandler({router: appRouter,createContext,responseMeta({ ctx, paths, type, errors }) {// assuming you have all your public routes with the keyword `public` in themconst allPublic = paths && paths.every((path) => path.includes('public'));// checking that no procedures erroredconst allOk = errors.length === 0;// checking we're doing a query requestconst isQuery = type === 'query';if (ctx?.res && allPublic && allOk && isQuery) {// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: {'cache-control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,},};}return {};},});
server.tstsximport * as trpc from '@trpc/server';import { inferAsyncReturnType } from '@trpc/server';import * as trpcNext from '@trpc/server/adapters/next';export const createContext = async ({req,res,}: trpcNext.CreateNextContextOptions) => {return {req,res,prisma,};};type Context = inferAsyncReturnType<typeof createContext>;export function createRouter() {return trpc.router<Context>();}const waitFor = async (ms: number) =>new Promise((resolve) => setTimeout(resolve, ms));export const appRouter = createRouter().query('public.slow-query-cached', {async resolve({ ctx }) {await waitFor(5000); // wait for 5sreturn {lastUpdated: new Date().toJSON(),};},});// Exporting type _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-exportexport type AppRouter = typeof appRouter;// export API handlerexport default trpcNext.createNextApiHandler({router: appRouter,createContext,responseMeta({ ctx, paths, type, errors }) {// assuming you have all your public routes with the keyword `public` in themconst allPublic = paths && paths.every((path) => path.includes('public'));// checking that no procedures erroredconst allOk = errors.length === 0;// checking we're doing a query requestconst isQuery = type === 'query';if (ctx?.res && allPublic && allOk && isQuery) {// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: {'cache-control': `s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,},};}return {};},});