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

Next.js13中使用router.refresh()出现无样式内容闪烁问题

解决Next.js 13中router.refresh()导致的字体FOUC问题

一、核心原因

router.refresh()会触发全页面的重新渲染与数据验证,连带重新加载字体资源;而next/font/google默认配置若未做好缓存或预加载,就会导致字体重新下载时出现无样式内容闪烁(FOUC)。

二、具体解决方法

1. 全局单例化字体配置

务必在根layout.tsx中全局创建字体实例,避免在组件内重复生成,确保字体资源的请求稳定:

// app/layout.tsx
import { Inter } from 'next/font/google';

// 全局单例字体实例,不要在子组件中重复定义
const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap', // 优先显示系统字体,待自定义字体加载后替换,减少闪烁
});

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="zh-CN" className={inter.variable}>
      <body className={`font-sans ${inter.className}`}>{children}</body>
    </html>
  );
}

2. 配置字体资源长期缓存

在next.config.js中为字体资源设置强缓存策略,避免每次刷新都重新下载:

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  headers: async () => {
    return [
      {
        source: '/fonts/(.*)', // 匹配next/font生成的字体文件路径
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=31536000, immutable', // 缓存1年且不可修改
          },
        ],
      },
    ];
  },
};

module.exports = nextConfig;

3. 改用局部数据更新替代全页刷新

如果业务场景允许,放弃router.refresh()的全页刷新,使用客户端状态管理工具(如SWR、React Query)做局部数据更新:

'use client';
import useSWR from 'swr';

const fetcher = (url) => fetch(url).then(res => res.json());

export function DataCard() {
  const { data, mutate } = useSWR('/api/user-data', fetcher);

  const handleUpdate = async () => {
    // 发送数据修改请求
    await fetch('/api/update-user', { method: 'POST', body: JSON.stringify({ name: 'New Name' }) });
    // 手动更新缓存,仅刷新当前组件数据
    mutate();
  };

  return (
    <div>
      <h3>{data?.name}</h3>
      <button onClick={handleUpdate}>修改名称</button>
    </div>
  );
}

三、Server Actions能否解决该问题?

Server Actions本身不会直接解决FOUC,但使用方式决定了是否会出现问题:

  • 如果用Server Actions结合局部状态更新(比如useState、SWR的mutate),仅刷新需要变更的UI部分,不会触发全页渲染和字体重新加载,自然不会有FOUC;
  • 但如果使用Server Actions后仍搭配router.refresh()触发全页刷新,还是会出现字体闪烁问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:15:08