Next.js 15 App Router 最佳实践:路由、缓存与数据获取

Next.js 15 App Router 最佳实践:路由、缓存与数据获取

Ethan
2025-06-20 发布 / 正在检测是否收录...

Next.js 15 将 Server Components 和 Server Actions 纳入稳定功能,Turbopack Dev 也达到生产可用状态,并重构了缓存策略。本文梳理 2025 年 Next.js 15 App Router 的核心最佳实践。

一、Server Components 优先策略

app/ 目录下的组件默认都是服务端组件,基本原则是:尽量让父组件(页面)是服务端组件负责取数据,把数据作为 props 传给客户端组件负责交互。

// ✅ 推荐:Server Component 直接获取数据
export default async function Page() {
  const data = await fetch('https://api.example.com/data');
  const json = await data.json();
  return <div>{json.title}</div>;
}

// ❌ 避免:不必要的 Client Component
'use client';
export default function Page() {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetch('/api/data').then(r => r.json()).then(setData);
  }, []);
  return <div>{data?.title}</div>;
}

二、数据获取策略

Next.js 对原生 fetch 做了扩展,支持缓存控制:

// ISR 模式:每 24 小时重新验证
fetch(url, { next: { revalidate: 86400 } });

// SSR 模式:每次请求都重新获取
fetch(url, { cache: 'no-store' });

// SSG 模式:永久缓存
fetch(url, { cache: 'force-cache' });

在 Server Component 中推荐使用原生 fetch 而非 axios,因为只有原生 fetch 能享受 Next.js 的缓存扩展能力。axios 在客户端组件中完全可用。

三、路由系统要点

文件即路由

  • app/page.tsx/
  • app/about/page.tsx/about
  • app/posts/[id]/page.tsx/posts/:id(动态路由)
  • app/blog/[...slug]/page.tsx/blog/*(捕获所有路由)

Next.js 15 重要变更:params 现在是 Promise 类型,需要使用 await:

export default async function PostPage({ params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  // ...
}

四、缓存策略重构

Next.js 15 将缓存从"隐式默认"改为"显式可控":

  • GET 路由处理程序默认不再缓存
  • 客户端路由缓存默认不再缓存页面组件
  • 开发者需要显式声明缓存策略

这一变更使行为更加可预测,但也要求开发者明确思考每个请求的缓存需求。

五、路由守卫实现

在项目根目录创建 middleware.ts

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')?.value;
  if (!token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
}

六、并行数据获取

利用 Promise.all 避免瀑布式请求:

const [user, posts, comments] = await Promise.all([
  getUser(params.id),
  getPosts(params.id),
  getComments(params.id),
]);
© 版权声明
THE END
喜欢就支持一下吧
点赞 1 分享 收藏

评论

博主关闭了当前页面的评论

Warning: file_put_contents(/var/www/html/usr/cache/pagecache/c8/c805a01c9435cebe2321d94cc6d38a34.cache): failed to open stream: No such file or directory in /var/www/html/usr/plugins/PageCache/Plugin.php on line 188