Data not updating when deployed Nextjs13 app on Vercel, despite using cache: 'no-store' in fetch request

huangapple go评论62阅读模式
英文:

Data not updating when deployed Nextjs13 app on Vercel, despite using cache: 'no-store' in fetch request

问题

I have a feed component in my application that fetches data from an API endpoint. The component works fine when I test it on my local build, but when I deploy it on Vercel, it doesn't fetch the latest data. I suspect this issue is related to caching. To address the problem, I added the cache: 'no-store' option to the fetch request, but it doesn't seem to solve the problem. I would appreciate any help or suggestions to resolve this issue.

"use client";

const fetchPosts = async () => {
  const response = await fetch("/api/prompt", {
    cache: 'no-store',
  });
  const data = await response.json();
  setAllPosts(data);
};

useEffect(() => {
  fetchPosts();
}, []);

GitHub Link:
https://github.com/justinwkUKM/promptify/blob/main/components/Feed.jsx

Note: 请提供在部署到 Vercel 时解决缓存问题的任何建议或解决方案。谢谢!

英文:

I have a feed component in my application that fetches data from an API endpoint. The component works fine when I test it on my local build, but when I deploy it on Vercel, it doesn't fetch the latest data. I suspect this issue is related to caching. To address the problem, I added the cache: 'no-store' option to the fetch request, but it doesn't seem to solve the problem. I would appreciate any help or suggestions to resolve this issue.

"use client";

  const fetchPosts = async () => {
    const response = await fetch("/api/prompt", {
      cache: 'no-store',
    });
    const data = await response.json();
    setAllPosts(data);
  };

  useEffect(() => {
    fetchPosts();
  }, []);

GitHub Link:
https://github.com/justinwkUKM/promptify/blob/main/components/Feed.jsx

Note: Please provide any suggestions or solutions for the caching issue when deploying on Vercel. Thank you!

答案1

得分: 2

这是您要翻译的内容:

"你和我遇到了完全相同的问题。我能够通过以下方式解决:

/app/api/prompt/route.js

import Prompt from "@models/prompt";
import { connectToDB } from "@utils/database";

export const revalidate = 1; //每1秒重新验证API
export const GET = async (request) => {
    try {
        await connectToDB()

        const prompts = await Prompt.find({}).populate('creator')

        return new Response(JSON.stringify(prompts), { status: 200 })
    } catch (error) {
        return new Response("无法获取所有提示", { status: 500 })
    }
} 

我无法真正解释为什么Next会以这种方式工作,但这对我有效。"

英文:

You have literally the exact same issue as me. I was able to find a fix with this:

/app/api/prompt/route.js

import Prompt from "@models/prompt";
import { connectToDB } from "@utils/database";

export const revalidate = 1; //revalidate api every 1 second
export const GET = async (request) => {
    try {
        await connectToDB()

        const prompts = await Prompt.find({}).populate('creator')

        return new Response(JSON.stringify(prompts), { status: 200 })
    } catch (error) {
        return new Response("Failed to fetch all prompts", { status: 500 })
    }
} 

I can't really explain why Next works this way, but this fixed it for me.

答案2

得分: 2

对于仍然在部署到 Vercel 时遇到此问题的任何人:

问题是由 Next.JS 静态渲染文件引起的。根据文档默认情况下,Next.js 静态渲染路由以提高性能。

您可以在执行 npm run build 时打印的输出中看到这一点。下面显示了输出的一个简单示例。

路由 (应用)
┌ ○ /api/prompt
└ λ /api/prompt/[id]

λ  (服务器)  服务器端在运行时呈现(使用 getInitialProps 或 getServerSideProps)
○  (静态)  自动呈现为静态 HTML(不使用初始属性)

为了防止 Next.JS 静态渲染此站点,它需要某种方式来知道它是动态的。根据文档如果发现动态函数或动态 fetch() 请求(无缓存),Next.js 将在请求时切换到动态渲染整个路由。

路由的静态和动态行为可以使用 Next.JS 的路由段配置功能来控制。

具体来说,您可以导出动态变量,并将其值设置为 'force-dynamic',如下所示

import Prompt from "@models/prompt";
import { connectToDB } from "@utils/database";

export const dynamic = 'force-dynamic';
export const GET = async (request) => {
  try {
    await connectToDB();

    const prompts = await Prompt.find({}).populate('creator');

    return new Response(JSON.stringify(prompts), { status: 200 });
  } catch (error) {
    return new Response("Failed to fetch all prompts", { status: 500 });
  }
}

这个导出确保了 Next.JS 动态呈现路由!

一个小侧记:
这在功能上类似于根据文档添加 export const revalidate = 0;

英文:

For anyone who is still encountering this issue when deploying to Vercel:

The issue is being caused by the file being rendered statically by Next.JS. According to the documentation: By default, Next.js statically renders routes to improve performance.

You can see this in the output printed when npm run build is executed. A simple example of the output is shown below.

Route (app)
┌ ○ /api/prompt
└ λ /api/prompt/[id]

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)

In order to prevent Next.JS from statically rendering this site it needs some way to know its dynamic. According to the documentation: if a dynamic function or a dynamic fetch() request (no caching) is discovered, Next.js will switch to dynamically rendering the whole route at request time.

The static and dynamic behavior of a route can be controlled using the Route Segment Config features of Next.JS

Specifically you can export the dynamic variable with the value of 'force-dynamic' as shown

import Prompt from "@models/prompt";
import { connectToDB } from "@utils/database";

export const dynamic = 'force-dynamic';
export const GET = async (request) => {
  try {
    await connectToDB();

    const prompts = await Prompt.find({}).populate('creator');

    return new Response(JSON.stringify(prompts), { status: 200 });
  } catch (error) {
    return new Response("Failed to fetch all prompts", { status: 500 });
  }
} 

This export ensures that Next.JS renders the route dynamically!

A little side note:
This is functionally similar to adding export const revalidate = 0; according to the docs.

答案3

得分: 0

我在部署我的应用程序到Vercel时遇到了类似的问题。然而,通过更新fetchPosts函数并包含以下更改,我成功解决了它:

const response = await fetch("/api/prompt", { next: { revalidate: 1 } });

此外,我还更新了app/api/prompt/route.js文件:

import Prompt from "@models/prompt";
import { connectToDatabase } from "@utils/database";
import { NextRequest, NextResponse } from "next/server";
import { revalidatePath } from "next/cache";

export const GET = async (request) => {
  try {
    await connectToDatabase();

    const prompts = await Prompt.find({}).populate("creator");

    // 动态获取路径
    const path = request.nextUrl.searchParams.get("path") || "/";

    revalidatePath(path);

    return NextResponse.json(prompts);
  } catch (error) {
    return new Response("无法获取所有提示", { status: 500 });
  }
};

有关详细说明,您可以参考此YouTube视频:
https://www.youtube.com/watch?v=TZXMT-EG7Ak&t=98s

希望这有助于您解决问题。

英文:

I encountered a similar issue when deploying my app on Vercel. However, I was able to resolve it by updating the fetchPosts function to include the following changes:

const response = await fetch("/api/prompt", { next: { revalidate: 1 } });

Additionally, I made updates to the app/api/prompt/route.js file

import Prompt from "@models/prompt";
import { connectToDatabase } from "@utils/database";
import { NextRequest, NextResponse } from "next/server";
import { revalidatePath } from "next/cache";

export const GET = async (request) => {
  try {
    await connectToDatabase();

    const prompts = await Prompt.find({}).populate("creator");

    //To dynamically get the path
    const path = request.nextUrl.searchParams.get("path") || "/";

    revalidatePath(path);

    return NextResponse.json(prompts);
  } catch (error) {
    return new Response("Failed to fetch all prompts", { status: 500 });
  }
};

For a detailed explanation, you can refer to this YouTube video:
https://www.youtube.com/watch?v=TZXMT-EG7Ak&t=98s

I hope that this helps you in resolving the issue.

huangapple
  • 本文由 发表于 2023年5月29日 19:07:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定