Next.js结合RTK Query无法重置缓存,求技术解决方案
解决Next.js + RTK Query服务端API调用缓存问题
问题背景
使用Next.js结合next-redux-wrapper和RTK Query在服务端发起外部API调用时,遇到API响应被缓存的问题,已尝试添加revalidate、配置fetchBaseQuery的cache: 'no-store'和next: { revalidate: 5 },均无效。当前实现代码:
CompaniesPage.getInitialProps = initialPagePropsWithCompanies; // --- import { createWrapper } from 'next-redux-wrapper'; const wrapper = createWrapper<ReturnType<typeof makeStore>>(makeStore); export const initialPagePropsWithCompanies = wrapper.getInitialPageProps((store: AppStore) => async () => { store.dispatch(api.endpoints.getHomePage.initiate()); await Promise.all(store.dispatch(api.util.getRunningQueriesThunk())); return { props: {} }; });
解决方案
1. 强制RTK Query刷新请求
RTK Query自身会缓存查询结果,即使Next.js不缓存,也可能返回旧数据。发起请求时添加forceRefetch: true强制刷新:
store.dispatch(api.endpoints.getHomePage.initiate(undefined, { forceRefetch: true }));
或者在API切片的endpoint定义中直接禁用RTK Query缓存:
endpoints: (builder) => ({ getHomePage: builder.query({ query: () => '/home', cacheTime: 0, // 立即清理缓存 staleTime: 0, // 数据立即过期 }), })
2. 彻底禁用Next.js服务端fetch缓存
在fetchBaseQuery配置中同时设置cache: 'no-store'和next: { revalidate: 0 },确保Next.js不对该请求进行缓存:
baseQuery: fetchBaseQuery({ baseUrl: `${process.env.NEXT_PUBLIC_PROTOCOL || 'https://'}${process.env.NEXT_PUBLIC_VERCEL_URL}/api`, headers: { 'x-telegram-query': typeof window !== 'undefined' ? window.Telegram.WebApp.initData : '', }, cache: 'no-store', next: { revalidate: 0 }, // 强制禁用Next.js缓存 }),
3. 调整getInitialProps的缓存策略
Next.js生产环境会缓存getInitialProps的执行结果,需在返回值中添加revalidate字段控制缓存有效期:
export const initialPagePropsWithCompanies = wrapper.getInitialProps((store: AppStore) => async () => { store.dispatch(api.endpoints.getHomePage.initiate(undefined, { forceRefetch: true })); await Promise.all(store.dispatch(api.util.getRunningQueriesThunk())); return { props: {}, revalidate: 5 // 每5秒重新生成页面数据 }; });
更推荐的方式:改用getServerSideProps替代getInitialProps,该API默认每次请求都执行,不会缓存结果:
export const getServerSideProps = wrapper.getServerSideProps((store) => async () => { store.dispatch(api.endpoints.getHomePage.initiate(undefined, { forceRefetch: true })); await Promise.all(store.dispatch(api.util.getRunningQueriesThunk())); return { props: {} }; });
4. 配置响应头禁用边缘缓存(如Vercel部署)
如果部署在Vercel等平台,可能存在边缘层缓存,需在服务端设置Cache-Control头:
export const initialPagePropsWithCompanies = wrapper.getInitialProps((store: AppStore) => async ({ res }) => { if (res) { // 设置响应头禁用缓存 res.setHeader('Cache-Control', 'no-store, max-age=0, must-revalidate'); } store.dispatch(api.endpoints.getHomePage.initiate(undefined, { forceRefetch: true })); await Promise.all(store.dispatch(api.util.getRunningQueriesThunk())); return { props: {} }; });
内容的提问来源于stack exchange,提问作者acidernt
相关产品推荐
相关产品推荐

