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

生产环境MongoDB insertOne()过慢,页面重载无法获取最新数据

问题:Next.js + MongoDB 生产环境插入数据后刷新无法立即看到新记录

我有一个基于MongoDB模板的新Next.js应用,执行简单的insertOne操作后重载页面,本地运行完全正常,但生产环境中这个过程需要几秒,导致页面重载无法获取到最新记录,必须再次刷新页面。我忽略了什么?


前端提交评论的代码

const submitComment = async(e:any) => {
    e.preventDefault();
      try {
       let response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/addPost`, 
{
        method: "POST",
        body: JSON.stringify({comment}),
        headers: {
           Accept: 'application/json, text/plain, */*',
          'Content-Type': 'application/json'
         }
       });
      response = await response.json();
      window.location.reload();
    }catch(err: any) {
      // console.log(`ERROR: ${err}`)
    }
  }

页面数据获取逻辑(getStaticProps)

export const getStaticProps: GetStaticProps = async () => {
  const posts = await getPosts();

  return {
    props: {
       posts: JSON.parse(JSON.stringify(posts))
    },
    revalidate: 10
  };
};

getPosts() 方法实现

let client;
let posts: any;

async function init() {
    try {
         client = await clientPromise;
        posts = client.db('hors-service').collection('posts');
    } catch (error) {
        throw new Error('Failed to establish connection to database');
    }
}

;(async () => {
    await init()
})()

export async function getPosts() {
    try {
        if(!posts) await init();
        const result = await posts
            .find()
            .map(
                (post: { _id: { toString: () => any; }; }) => ({...post, _id: post._id.toString()}))
            .sort( {
                _id: -1
            })
            .toArray();
        return result;
    } catch (error) {
        return { error: 'Failed to fetch posts'};
    }
}

MongoDB配置文件

import { MongoClient } from 'mongodb';

if (!process.env.MONGODB_URI) {
  throw new Error('Please add your Mongo URI to .env.local');
}

const uri = process.env.MONGODB_URI;
const options = {};

let client;
let clientPromise: Promise<any>;

declare global {
  var _mongoClientPromise: Promise<MongoClient>;
}

if (process.env.NODE_ENV === 'development') {
  // In development mode, use a global variable so that the value
  // is preserved across module reloads caused by HMR (Hot Module Replacement).
  if (!global._mongoClientPromise) {
    client = new MongoClient(uri, options);
    global._mongoClientPromise = client.connect();
  }
  clientPromise = global._mongoClientPromise;
} else {
  // In production mode, it's best to not use a global variable.
  client = new MongoClient(uri, options);
  clientPromise = client.connect();
}

// Export a module-scoped MongoClient promise. By doing this in a
// separate module, the client can be shared across functions.
export default clientPromise;

问题原因与解决方法

核心原因

你使用了 getStaticProps + revalidate:10 开启了增量静态再生(ISR),生产环境下页面会被静态缓存。即便插入了新数据,页面刷新时大概率加载的还是缓存版本,要等10秒后才会重新生成页面。而本地开发时Next.js默认禁用静态缓存,所以能立即看到新数据。

解决思路1:改用SWR/React Query做客户端数据获取

放弃依赖 getStaticProps 的静态数据,改用客户端数据获取库(比如SWR),每次页面刷新都会从API拉取最新数据:

import useSWR from 'swr';

const fetcher = async () => {
  const res = await fetch('/api/getPosts');
  return res.json();
};

export default function PostsPage() {
  const { data: posts, error } = useSWR('/api/getPosts', fetcher);

  if (error) return <div>加载失败</div>;
  if (!posts) return <div>加载中...</div>;

  // 渲染posts列表
  return (
    <div>
      {posts.map(post => (
        <div key={post._id}>{post.comment}</div>
      ))}
    </div>
  );
}

同时新增 pages/api/getPosts.ts 接口:

import clientPromise from '../../lib/mongodb';

export default async function handler(req, res) {
  const client = await clientPromise;
  const db = client.db('hors-service');
  const posts = await db.collection('posts')
    .find()
    .map(post => ({...post, _id: post._id.toString()}))
    .sort({_id: -1})
    .toArray();
  
  res.status(200).json(posts);
}

解决思路2:强制触发ISR重新生成页面

在插入数据的API接口(/api/addPost)中,调用Next.js的 revalidatePath 方法强制刷新页面的静态缓存:

// pages/api/addPost.ts
import clientPromise from '../../lib/mongodb';
import { revalidatePath } from 'next/cache';

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method Not Allowed' });
  }

  const { comment } = req.body;
  const client = await clientPromise;
  const db = client.db('hors-service');
  
  await db.collection('posts').insertOne({ comment, createdAt: new Date() });

  // 强制重新生成帖子列表页面(替换成你的实际页面路径)
  revalidatePath('/');

  res.status(200).json({ success: true });
}

这样插入数据后,Next.js会立即重新生成页面的静态版本,用户刷新就能看到新数据,同时保留ISR的缓存优势。

解决思路3:改用getServerSideProps

如果页面不需要静态缓存,直接用 getServerSideProps 代替 getStaticProps,每次页面请求都会从数据库拉取最新数据:

export const getServerSideProps: GetServerSideProps = async () => {
  const posts = await getPosts();

  return {
    props: {
       posts: JSON.parse(JSON.stringify(posts))
    }
  };
};

但这种方式会增加服务器负载,适合数据更新频繁且访问量不高的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 06:40:41