预渲染Black Friday页面过期后样式异常,如何修复?
问题描述
我希望预渲染Black Friday页面,但页面过期后显示过期页面。当前代码存在的问题是:页面会先加载Black Friday页面,随后加载过期页面(推测是因为过期页面加载耗时更长),最终用户看到的过期页面混合了Black Friday页面的样式。
复现步骤:
- 用户在页面未过期时加载Black Friday页面
- 等待页面过期
- 刷新页面
- 用户看到过期页面,但样式显示不正确
当前代码:
export async function getStaticPaths() { const blackFridaylugs = await ContentfulApi.getBlackFridaySlugs(); const paths = blackFridaySlugs.map((item) => ({ params: { slug: item.slug } })); return { paths, fallback: "blocking" }; } export async function getStaticProps({ preview = false, params, previewData }) { const page = await ContentfulApi.getBlackFridayPromoBySlug(params.slug, { preview, enviroment: previewData?.enviroment }); const expiredPage = await ContentfulApi.getPageContentBySlug( "expired-page", { preview, enviroment: previewData?.enviroment } ); const globalSettings = await ContentfulApi.getGlobalSettings({ preview }); return { props: { page, expiredPage, globalSettings }, revalidate: 100 }; } function BlackFridayPages({ page, expiredPage, globalSettings }) { const blackFridayEndDate = new Date('2023-02-20') //Change this to test const now = new Date(); const expired = blackFridayEndDate < now if (expired) { return ( <ExpiredPage expiredPage={expiredPage} /> ); } return ( <> <BlackFridayPage /> </> ); //no extra conditional because I want it pre-rendered. Am I not allowed to do this? } export default BlackFridayPages;
修复方案
1. 在服务端提前判断过期状态,只返回对应页面数据
问题核心是当前不管页面是否过期,都会同时请求两类页面数据,前端渲染时才做切换,导致预渲染缓存的旧页面样式残留。应该在getStaticProps阶段就判断过期状态,只获取需要的页面数据,从根源避免不必要的资源加载,同时确保预渲染/重新验证时直接生成正确页面。
修改后的getStaticProps:
export async function getStaticProps({ preview = false, params, previewData }) { const blackFridayEndDate = new Date('2023-02-20'); const now = new Date(); const expired = blackFridayEndDate < now; let pageData; if (expired) { // 过期时仅请求过期页面数据 pageData = await ContentfulApi.getPageContentBySlug( "expired-page", { preview, enviroment: previewData?.enviroment } ); } else { // 未过期时请求Black Friday页面数据 pageData = await ContentfulApi.getBlackFridayPromoBySlug(params.slug, { preview, enviroment: previewData?.enviroment }); } const globalSettings = await ContentfulApi.getGlobalSettings({ preview }); return { props: { pageData, isExpired: expired, globalSettings }, revalidate: 100 }; }
对应组件修改:
function BlackFridayPages({ pageData, isExpired, globalSettings }) { if (isExpired) { return <ExpiredPage expiredPage={pageData} />; } return <BlackFridayPage page={pageData} />; }
2. 确保组件样式隔离
若仍存在样式混合问题,需检查两个页面组件的样式是否存在全局污染:
- 避免使用无范围限制的全局CSS类名,改用CSS Modules、styled-components等模块化方案
- 给两个组件的根元素添加独立的类名,用于隔离样式作用域
3. 优化重新验证时机
当前revalidate: 100设置为每100秒重新生成页面,可根据过期时间动态调整该值,确保过期后页面能及时更新:
// 在getStaticProps中添加 const timeUntilExpiry = blackFridayEndDate.getTime() - now.getTime(); // 过期前根据剩余时间设置重新验证间隔,过期后保持60秒一次 const revalidateTime = timeUntilExpiry > 0 ? Math.max(60, Math.floor(timeUntilExpiry / 1000)) : 60; return { props: { /* ... */ }, revalidate: revalidateTime };
内容的提问来源于stack exchange,提问作者journalsup
相关产品推荐
相关产品推荐

