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-caching för att leverera data till dina användare så snabbt som möjligt.
Var alltid försiktig med cachning - särskilt vid hantering av personuppgifter.
Eftersom batchning är aktiverat som standard rekommenderas att ställa in dina cache-headers i responseMeta-funktionen och se till att inga samtidiga anrop innehåller personlig data. Alternativt kan du utesluta cache-headers helt om det finns en auth-header eller cookie.
Du kan också använda en splitLink för att separera publika förfrågningar från de som ska vara privata och ocachade.
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 appen statiskt utan SSG; läs denna Twitter-tråd för mer insikt.
Exempelkod
utils/trpc.tsxtsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../server/routers/_app';export const trpc = createTRPCNext<AppRouter>({config(config) {if (typeof window !== 'undefined') {return {links: [httpBatchLink({url: '/api/trpc',}),],};}const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {links: {http: httpBatchLink({url,}),},};},ssr: true,responseMeta(opts) {const { clientErrors } = opts;if (clientErrors.length) {// propagate http first error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: new Headers([['cache-control',`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,],]),};},});
utils/trpc.tsxtsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import type { AppRouter } from '../server/routers/_app';export const trpc = createTRPCNext<AppRouter>({config(config) {if (typeof window !== 'undefined') {return {links: [httpBatchLink({url: '/api/trpc',}),],};}const url = process.env.VERCEL_URL? `https://${process.env.VERCEL_URL}/api/trpc`: 'http://localhost:3000/api/trpc';return {links: {http: httpBatchLink({url,}),},};},ssr: true,responseMeta(opts) {const { clientErrors } = opts;if (clientErrors.length) {// propagate http first error from API callsreturn {status: clientErrors[0].data?.httpStatus ?? 500,};}// cache request for 1 day + revalidate once every secondconst ONE_DAY_IN_SECONDS = 60 * 60 * 24;return {headers: new Headers([['cache-control',`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,],]),};},});
Cachning av API-svar
Eftersom alla queries är vanliga HTTP-GET-anrop kan vi använda normala HTTP-headers för att cacha svar, göra svaren blixtsnabba, ge databasen en paus och enkelt skala ditt API till astronomiska användarmängder.
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 { initTRPC } 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 = 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 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(opts) {const { ctx, paths, errors, type } = opts;// 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: new Headers([['cache-control',`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,],]),};}return {};},});
server.tstsximport { initTRPC } 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 = 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 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(opts) {const { ctx, paths, errors, type } = opts;// 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: new Headers([['cache-control',`s-maxage=1, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,],]),};}return {};},});