Next.js如何在构建时静态渲染前3页,其余页面实时渲染?
在Next.js中实现指定分页页面预渲染+其余页面实时获取
要实现构建阶段预渲染前3页、其余页面实时加载的需求,核心是结合Next.js的静态生成(SSG)和客户端数据获取能力,具体步骤如下:
1. 创建动态路由页面
在pages目录下创建动态路由文件,比如pages/posts/[page].js,用来处理所有分页请求。
2. 配置getStaticPaths指定预渲染页面
通过getStaticPaths告诉Next.js构建时要预渲染哪些页面(这里是第1-3页),同时设置fallback: true,让未预渲染的页面能正常访问并在客户端动态加载数据:
export async function getStaticPaths() { // 生成前3页的路由参数 const paths = Array.from({ length: 3 }, (_, i) => ({ params: { page: (i + 1).toString() }, })); // fallback: true 表示未在paths中的页面会交由客户端处理 return { paths, fallback: true }; }
3. 用getStaticProps获取预渲染页面的数据
对getStaticPaths指定的页面,在getStaticProps中获取对应分页的数据并传递给组件:
export async function getStaticProps({ params }) { const page = parseInt(params.page); // 替换成你的实际数据接口 const res = await fetch(`https://your-api.com/posts?page=${page}`); const data = await res.json(); return { props: { posts: data.posts, currentPage: page, isPreRendered: true, // 标记当前页面是否为预渲染页面 }, // 可选:让预渲染页面定期自动更新(比如每60秒重新生成) // revalidate: 60, }; }
4. 组件内部处理实时加载逻辑
在组件中判断当前页面是否为预渲染页面(或直接判断页码是否大于3),如果是,则在客户端发起请求获取实时数据。这里推荐用SWR(Next.js官方推荐的数据获取库),它自带缓存和重新验证能力,体验更流畅:
先安装SWR:
npm install swr
组件代码示例:
import { useState, useEffect } from 'react'; import useSWR from 'swr'; const PostsPage = ({ posts: initialPosts, currentPage: initialPage, isPreRendered }) => { const [currentPage, setCurrentPage] = useState(initialPage); const [posts, setPosts] = useState(initialPosts); // 定义数据获取函数 const fetcher = async (url) => { const res = await fetch(url); return res.json(); }; // 非预渲染页面(页码>3)用SWR实时拉取数据 const { data, error } = useSWR( !isPreRendered ? `https://your-api.com/posts?page=${currentPage}` : null, fetcher ); // 当SWR拿到新数据时更新页面状态 useEffect(() => { if (data) { setPosts(data.posts); } }, [data]); // 分页切换逻辑 const handlePageChange = (page) => { setCurrentPage(page); // 非预渲染页面切换时,SWR会自动重新发起请求 }; if (error) return <div>加载失败,请稍后重试</div>; // 未预渲染页面在数据加载前显示加载状态 if (!isPreRendered && !data) return <div>加载中...</div>; return ( <div> <h1>第 {currentPage} 页帖子</h1> <div className="posts-list"> {posts.map((post) => ( <div key={post.id} className="post-card"> <h2>{post.title}</h2> <p>{post.excerpt}</p> </div> ))} </div> <div className="pagination"> {Array.from({ length: 10 }, (_, i) => ( <button key={i+1} onClick={() => handlePageChange(i+1)} disabled={currentPage === i+1} className={currentPage === i+1 ? 'active' : ''} > {i+1} </button> ))} </div> </div> ); }; export default PostsPage;
关键细节说明
fallback: true:未预渲染的页面会先返回一个包含客户端脚本的空HTML,避免404,之后在客户端动态拉取数据渲染。- 如果希望非预渲染页面第一次访问时用服务器端渲染(SSR)、后续缓存,可以把
fallback设为'blocking',但这样无法保证数据实时性,需根据需求选择。 - SWR的缓存机制能让用户切换分页时快速响应,同时可通过配置保证数据新鲜度。
内容的提问来源于stack exchange,提问作者Nishanth B.S
相关产品推荐
相关产品推荐

