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

Next.js如何避免SSG静态页先加载、子域名判定前的页面闪烁问题

问题解答

基础结论

  • getStaticProps是构建阶段运行的函数,无法获取用户请求时的URL、hostname、子域名等动态请求数据,所以你没法在这个函数里拿到subdomain做判断。
  • 你遇到的闪烁根本原因是:SSG生成的静态页默认嵌入的是主页面内容,页面到客户端后Hydration完成才会执行getSubdomain()判断子域名切换内容,中间的时间差就导致了主页面一闪而过的问题。

解决闪烁的可选方案

方案1:使用Middleware重写路径(推荐,保留SSG优势)

Next.js的Middleware运行在请求到达静态资源之前,能拿到请求的完整host信息,你可以根据子域名重写请求路径,完全避免客户端切换逻辑:

  1. 项目根目录新增middleware.ts:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  const hostname = request.headers.get('host') || ''
  // 替换为你的主域名,可自行适配多环境、www前缀等逻辑
  const subdomain = hostname.replace('.hostname.com', '').replace('www.', '')
  
  // 存在有效子域名时,重写到对应子域名页面路径,浏览器地址栏不会变化
  if (subdomain && subdomain !== '') {
    return NextResponse.rewrite(new URL(`/${subdomain}`, request.url))
  }
  return NextResponse.next()
}

// 配置只匹配首页请求
export const config = {
  matcher: '/',
}
  1. 新增pages/[subdomain]/index.tsx页面,通过getStaticPaths预生成所有企业的静态页面,或者开启fallback: 'blocking'用ISR增量生成,访问时直接返回对应子域名的静态内容,完全没有闪烁。

方案2:改用SSR(实现最简单)

如果不需要纯静态的SSG优势,直接把getStaticProps替换为getServerSideProps,服务端请求时直接判断子域名,返回对应内容:

export const getServerSideProps: GetServerSideProps = async (context) => {
  const { req } = context
  const hostname = req.headers.host || ''
  const subdomain = hostname.replace('.hostname.com', '').replace('www.', '')
  // 根据子域名加载对应内容,主域名加载home.md
  const content = await import(`../content/pages/${subdomain || 'home'}.md`);

  return { props: { content: content.default, subdomain } };
};

组件直接用props传入的subdomain做判断即可,首屏返回的就是正确内容,不会有切换闪烁。

方案3:客户端降级方案(不推荐)

如果一定要保留现有SSG逻辑,可以在组件初始渲染时先展示骨架屏/空白,等客户端判断完子域名再渲染对应内容:

const HomePage: NextPage<Props> = ({ content }) => {
  const { attributes } = content;
  const [isHydrated, setIsHydrated] = useState(false)
  const subdomain = getSubdomain();

  useEffect(() => {
    setIsHydrated(true)
  }, [])

  if (!isHydrated) return <div className="h-screen w-full bg-white"></div> // 骨架屏可自行替换

  return (
    <>
      <SEO />
      <div className="m-auto max-w-7xl">
        {subdomain ? (
          <SubdomainDataComponent subdomain={subdomain} />
        ) : (
          <MainPage />
        )}
      </div>
    </>
  );
};

内容的提问来源于stack exchange,提问作者Anton Karatkevich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:24:02