如何分批导出大型Next.js静态站点?
问题描述
我正在为我的站点使用Next.js的Static HTML Export功能,该站点包含1000万个静态页面,但构建应用时遇到了内存问题。
是否可以分批导出?比如第一次构建导出10万个页面,第二次再导出10万个,以此类推?
为了控制成本,我不想使用Incremental Static Regeneration或getServerSideProps。
该站点使用MongoDB,仅包含两个页面:
index.js [postPage].js
首页代码如下:
export async function getStaticProps() { const { db } = await connectToDatabase(); const postsFeed = await db .collection("myCollection") .aggregate([{ $sample: { size: 100 } }]) .toArray(); return { props: { postsFeed: JSON.parse(JSON.stringify(postsFeed)), }, }; }
文章页代码如下:
export async function getStaticPaths() { const { db } = await connectToDatabase(); const posts = await db .collection("myCollection") .find({}) .toArray(); const paths = posts.map((data) => { return { params: { postPage: data.slug.toString(), } } }) return { paths, fallback: 'blocking' } } export async function getStaticProps(context) { const postSlug = context.params.postPage; const { db } = await connectToDatabase(); const posts = await db .collection("myCollection") .find({ slug: { $eq: postSlug } }) .toArray(); const postsFeed = await db .collection("myCollection") .aggregate([{ $sample: { size: 100 } }]) .toArray(); return { props: { posts: JSON.parse(JSON.stringify(posts)), postsFeed: JSON.parse(JSON.stringify(postsFeed)), }, }; }
解决方案
1. 改造getStaticPaths实现分批拉取路径
当前getStaticPaths一次性拉取1000万条数据,是内存溢出的核心原因。通过MongoDB分页查询+环境变量控制,实现批次导出:
- 新增环境变量
EXPORT_BATCH_START(起始偏移量)和EXPORT_BATCH_SIZE(单批次数量),指定当前导出的范围。 - 修改文章页的
getStaticPaths代码:
export async function getStaticPaths() { const { db } = await connectToDatabase(); // 读取环境变量,默认值可按需调整 const start = parseInt(process.env.EXPORT_BATCH_START || 0); const size = parseInt(process.env.EXPORT_BATCH_SIZE || 100000); const posts = await db .collection("myCollection") .find({}) .skip(start) .limit(size) .toArray(); const paths = posts.map((data) => ({ params: { postPage: data.slug.toString(), } })); return { paths, fallback: false, // 仅导出当前批次页面,避免触发动态生成 }; }
2. 分批执行导出命令
每次导出前设置对应环境变量,执行Next.js构建导出命令,完成后合并静态文件:
# 第一批次:导出前10万条页面 EXPORT_BATCH_START=0 EXPORT_BATCH_SIZE=100000 next build && next export # 第二批次:导出第10万-20万条页面 EXPORT_BATCH_START=100000 EXPORT_BATCH_SIZE=100000 next build && next export # 后续批次以此类推,直到所有页面导出完成
注意:每次导出后,需将out目录下的文章页面(如out/[postPage]相关文件)复制到统一的静态文件存储目录,避免被下一次导出覆盖。
3. 处理首页重复生成问题
首页每次构建都会重新生成,可按以下方式处理:
- 第一次导出时备份首页文件,后续批次导出后,将备份的首页文件替换回
out目录,再合并到存储目录。 - 或者通过环境变量控制首页的
getStaticProps,仅在第一次构建时生成首页(需额外添加判断逻辑)。
4. 额外优化点
- 避免文章页重复执行
$sample查询:提前将首页的postsFeed生成静态JSON文件,文章页直接读取该文件,减少数据库查询和内存占用。 - 提升Node.js内存限制:构建前加上
NODE_OPTIONS="--max-old-space-size=8192"(数值根据服务器内存调整),临时缓解内存压力。
内容的提问来源于stack exchange,提问作者Tribe56123
相关产品推荐
相关产品推荐

