Next.js:如何缓存每天只更改一次的数据?

问题描述 投票:0回答:1

我有一个使用 Next.js 的单页应用程序。我正在建立一个类似于 https://nflscorigami.com/ 但针对 NBA 的网站。在我的 postgresql 数据库中,我有一个包含大约 70k 行的表,其中包含每场 NBA 比赛。

在我的 trpc API 中我有

getGames: publicProcedure.query(async ({ ctx }) => {
    const allGames = await ctx.db.query.nbaGames.findMany();

    return {
      games: allGames,
    };
  }),

在我的主要图表组件中,我使用

获取此数据

const { data: gamesData, isLoading: loadingGamesData } = api.game.getGames.useQuery();

我在热图中呈现数据,热图加载大约需要 10 秒。数据集只会在当天的比赛结束后更新一次。如何将这些数据缓存 1 天,以减少每次打开和刷新页面时的加载时间和数据库请求?

我尝试更改 React Query 的 staleTime 和 gcTime 但这没有帮助。我还尝试了 trpc 文档在https://trpc.io/docs/server/caching中建议的内容。

export function TRPCReactProvider(props: { children: React.ReactNode }) {
  const queryClient = getQueryClient();
  queryClient.setDefaultOptions({
    queries: {
      staleTime: 12 * (60 * 60 * 1000), // 12 hours
      gcTime: 12 * (60 * 60 * 1000), // 12 hours
    },
  });

  const [trpcClient] = useState(() =>
    api.createClient({
      links: [
        loggerLink({
          enabled: (op) =>
            process.env.NODE_ENV === "development" ||
            (op.direction === "down" && op.result instanceof Error),
        }),
        unstable_httpBatchStreamLink({
          transformer: SuperJSON,
          url: getBaseUrl() + "/api/trpc",
          headers: () => {
            const headers = new Headers();
            headers.set("x-trpc-source", "nextjs-react");
            const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
            headers.set(
              "cache-control",
              `s-maxage=${ONE_DAY_IN_SECONDS}, stale-while-revalidate=${ONE_DAY_IN_SECONDS}`,
            );
            return headers;
          },
        }),
      ],
    }),
  );

  return (
    <QueryClientProvider client={queryClient}>
      <api.Provider client={trpcClient} queryClient={queryClient}>
        {props.children}
      </api.Provider>
    </QueryClientProvider>
  );
}
next.js caching react-query next.js14 trpc
1个回答
0
投票

您的方法的主要问题是您没有正确利用 Next.js 的功能,因为:

A) 通过从客户端组件获取,您需要一个中间人(您的 API),这会增加延迟。此外,客户端将必须接收所有 70k 记录,并且我假设计算热图的值,这至少可以说并不理想。
B) 如果用户浏览应用程序并返回到您的热图,客户端上的缓存可能会有所帮助,但考虑到您只有一个页面,我认为这没有太多用处。


最有前途的方法是使用 Next.js 的 ISR 功能(增量静态再生)来获取数据,在服务器上对热图进行计算,然后使用以下方法将此数据缓存所需的持续时间:

export const revalidate
变量。鉴于您使用 tRPC,您需要实例化一个可以在服务器上运行的 tRPC 客户端,并使用它来获取 服务器组件中的数据,同时利用 ISR

我头顶的一个例子可能看起来像这样(还没有测试过):

服务器客户端.ts

export const trpcProxyClient = createTRPCProxyClient<AppRouter>({
    transformer: superjson,
    links: [
        httpBatchLink({
            url: getBaseUrl() + "/api/trpc",
        }),
    ],
});

export const tRPCServerClient = createServerSideHelpers({
    client: trpcProxyClient,
});

页面.tsx

(假设您正在使用App Router

export const revalidate = 60

// calculate expensive stuff here
const expensiveCalculationForHeatmap = (games) => {}
 
export default async function Page() {
 const { data } = await tRPCServerClient.games.getAll.fetch()
 const transformedData = expensiveCalculationForHeatmap(data)
  return (
   <HeatmapClientComponent data={transformedData}/>
  )
}
© www.soinside.com 2019 - 2024. All rights reserved.