You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

预渲染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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 16:30:46