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

升级Next.js至v13版本:ISR错误处理与重验证配置问题

Next.js 13 错误场景下的动态重验证解决方案

针对你从v12升级到v13后无法在错误场景设置60秒重验证的问题,以下是两种贴合你原有逻辑的解决方案:

方案一:复用notFound() + 独立错误页面设置重验证

这个方案完全对应你v12中返回{ notFound: true, revalidate: 60 }的逻辑:

步骤1:在新闻页面组件中捕获错误并触发404

import { notFound } from 'next/navigation';
import type { FetchNews, SimplifiedArticle } from './your-types';

// 你的Firebase数据获取函数保持不变
async function fetchCategoryData(category: string): Promise<SimplifiedArticle[]> {
  const newsDocRef = collection(firestore, "news");
  const q = query(
    newsDocRef,
    where("category", "==", category),
    orderBy("publishedAt", "desc"),
    limit(5)
  );
  const querySnapshot = await getDocs(q);
  return querySnapshot.docs.map((doc) => {
    const docData = doc.data();
    return {
      title: docData.title || "",
      url: docData.url || "",
      imageUrl: docData.imageUrl || "",
      description: docData.description || "",
      publishedAt: docData.publishedAt || "",
      content: docData.content || "",
      source: docData.source || "",
    };
  });
}

// 正常页面设置3600秒重验证
export const revalidate = 3600;

export default async function NewsPage() {
  let news: FetchNews;

  try {
    // 原有数据获取逻辑迁移到组件内部
    news = await Promise.all(
      categories.map(async (category) => ({
        [category]: await fetchCategoryData(category),
      }))
    ).then(Object.assign.bind(null, {}));
  } catch (error) {
    console.log("News data fetch error: ", error);
    // 触发404,跳转到对应的not-found页面
    notFound();
  }

  // 正常渲染数据
  return (
    <div className="news-container">
      {/* 渲染你的新闻内容 */}
    </div>
  );
}

步骤2:创建独立的404错误页面并设置60秒重验证

在你的新闻页面同级目录下创建not-found.tsx(或.jsx):

// app/news/not-found.tsx
export const revalidate = 60; // 错误场景下60秒自动重验证

export default function NotFoundPage() {
  return (
    <div className="not-found">
      <h2>加载失败,正在重试...</h2>
    </div>
  );
}

原理说明:当数据获取失败调用notFound()时,Next.js会渲染这个独立的not-found页面,该页面的revalidate设置为60秒,会自动每1分钟重新尝试获取数据,成功后自动返回正常页面。

方案二:在当前页面处理错误并动态控制缓存

如果你不想跳转到404页面,而是在原页面显示错误状态并动态调整重验证时间,可以使用Next.js的缓存标签功能:

import { revalidateTag, unstable_cache } from 'next/cache';
import type { FetchNews, SimplifiedArticle } from './your-types';

// 用unstable_cache包裹数据获取函数,添加缓存标签
const fetchNewsData = unstable_cache(
  async () => {
    return Promise.all(
      categories.map(async (category) => ({
        [category]: await fetchCategoryData(category),
      }))
    ).then(Object.assign.bind(null, {}));
  },
  ['news-data-cache'], // 自定义缓存标签
  { revalidate: 3600 } // 正常情况3600秒重验证
);

// 你的Firebase数据获取函数保持不变
async function fetchCategoryData(category: string): Promise<SimplifiedArticle[]> {
  // ... 原有代码
}

export default async function NewsPage() {
  try {
    const news = await fetchNewsData();
    return (
      <div className="news-container">
        {/* 渲染正常内容 */}
      </div>
    );
  } catch (error) {
    console.log("News data fetch error: ", error);
    // 立即触发缓存重验证,同时设置页面在60秒后再次尝试
    await revalidateTag('news-data-cache');
    
    // 显示错误提示
    return (
      <div className="error-state">
        <p>新闻加载失败,将在1分钟后重试</p>
      </div>
    );
  }
}

// 基础重验证时间设置为60秒,结合revalidateTag实现动态控制
export const revalidate = 60;

原理说明:通过unstable_cache给数据请求打标签,错误时调用revalidateTag立即清除缓存,同时页面本身设置60秒重验证,确保错误状态下会频繁重试,正常状态下缓存通过unstable_cache的3600秒设置生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 18:47:52