Next.js Discord

Discord Forum

Getting stale data on build (static generation) - App dir

Unanswered
Philippine Crocodile posted this in #help-forum
Open in Discord
Philippine CrocodileOP
I am using Strapi as a CMS, and every time I make changes, it triggers the build and deployment of my Next.js static frontend hosted on Netlify.

However, I've observed that the fetched data doesn't update consistently. Only the generateStaticParams function appears to be working correctly. How can I ensure the data is revalidated every time I build the static site?

next 14.0.4 - app dir

Thank you in advance for any help

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: "export",
};

module.exports = nextConfig;


src/app/page.tsx
async function getData() {
  const res = await fetch(
    "https://strapi.../api/works"
  );
  if (!res.ok) {
    throw new Error("Failed to fetch data");
  }
  return res.json();
}

export default async function Home() {
  const data = await getData();

  return (
    <main>
      {data.map((work: Work) => (
        <Link
          key={work.id}
          className="py-3"
          href={`/works/${work.attributes.slug}`}
        >
          {work.attributes.title}
        </Link>
      ))}
    </main>
  );
}


src/app/works/[slug]/page.tsx
export async function generateStaticParams() {
  const works = await fetch(
    "https://strapi.../api/works"
  ).then((res) => res.json());

  return works.map((work: Work) => ({
    slug: work.attributes.slug,
  }));
}

async function fetchWork(slug: string) {
  const filteredWorks = await fetch(
    `https://strapi.../api/works?filters[slug][$eq]=${slug}`
  ).then((res) => res.json());
  return filteredWorks.data[0];
}

export default async function Page({ params }: { params: { slug: string } }) {
  const work = await fetchWork(params.slug);

  if (!work) {
    notFound();
  }

  return (
    <div className="flex min-h-screen flex-col p-24">
      <h1 className="text-3xl font-bold">{work.attributes.title}</h1>
    </div>
  );
}

31 Replies

add this to your fetch reqeuests.
next: {
  revalidate: 0;
}
@Jesse add this to your fetch reqeuests. js next: { revalidate: 0; }
Philippine CrocodileOP
Thank you for the suggestion. I tried this method, but it seems to make the route dynamic (no longer static). I would simply like to deploy a static version of the site with the data updated to the latest build, and that is not possible this way.

Sorry I'm new to Next.js, maybe I'm missing something
you have to pick one or the other
the only compromise is settings the revalidate to something like 1800, which is 30 minutes
@Jesse you can't create a static version, but want the data to be dynamic
Philippine CrocodileOP
I'm quite sure this could be done with the pages dir. They are not dynamic data since they would be added at the time of the build triggered by a webhook.

(I don't think this is the best method), but for the size of the project I have to do, I believe it is the most "optimal"
Hello there, @Philippine Crocodile you can revalidate page or layout on-demand by creating API endpoint to which you can pass URL that you want to revalidate, this will cause re rendering of this page using fresh data.

https://nextjs.org/docs/app/api-reference/functions/revalidatePath

Hope this will help 😄
normally you'd use revalidation here as @Z4NR34L stated
a full rebuild is inefficient anyway but I don't get why you'd get stale data in this case, on the contrary a rebuild is overkill
revalidation will simply rerender relevant pages
Just like @Eric Burel said, but if you want more help from us, access to repository or minimal reproduction would be perfect to dig dipper into it.

https://vercel.com/guides/creating-a-minimal-reproducible-example
Philippine CrocodileOP
@Eric Burel @Z4NR34L Thanks for the answers! I might be mistaken, but in my case, I need a static site that is updated promptly with the latest changes happening in the CMS. There won't be many modifications, but the ones that occur should be immediately visible. A regular WordPress would have been perfect, but I wanted to try something new in the most cost-effective way (for free). Uploading the static site to Netlify and doing a few builds per week seemed "clever" to me. 😅 But I remain open to suggestions
@Jesse I don't think there's a way you can sync the changes in your CMS to the static website, unless you do it manually, or have a really long revalidate depending on how often you're gonna update your CMS.
Philippine CrocodileOP
with Netlify hooks and strapi is very simple and It should happen only a couple of times a week.

The only problem is that it doesn't update the data from the fetch (except for the one inside generateStaticParams).

I would like to provide you an example, but I'm not sure which public API to use so that you can test it.
Philippine CrocodileOP
I can confirm that this behavior occurs only in the 'app router' version and not in the 'pages router' version.

To replicate it:

1) Create a new project by selecting the 'app router.'
npx create-next-app@latest (next 14.0.4)

2) Add "output: export" to next.config.js file to build next as a static site.
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: "export",
};
module.exports = nextConfig;

3) Fetch any random data (in this case, from 'https://yesno.wtf/api').
My src/app/page.tsx looks like this:
async function getData() {
  const res = await fetch("https://yesno.wtf/api");
  if (!res.ok) {
    throw new Error("Failed to fetch data");
  }
  return res.json();
}

export default async function Home() {
  const res = await getData();
  return (
    <main className="flex min-h-screen flex-col p-12">
      with app router
      <picture>
        <img
          src={res.image}
          alt={res.answer}
          className="w-96 h-96 object-contain"
        />
      </picture>
      <p>{res.answer}</p>
    </main>
  );
}

4) Build the project.
5) Rebuild it, and the data will not change.
---

In the 'pages router,' when fetching data inside the 'getStaticProps' function, the data will be different with each build.

for reference my pages/index.tsx is this
import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"] });

export default function Home({
  yesOrNot,
}: {
  yesOrNot: {
    answer: string;
    forced: boolean;
    image: string;
  };
}) {
  return (
    <main className={`flex min-h-screen flex-col p-24 ${inter.className}`}>
      with pages dir
      <picture>
        <img
          src={yesOrNot.image}
          alt={yesOrNot.answer}
          className="w-96 h-96 object-contain"
        />
      </picture>
      <p>{yesOrNot.answer}</p>
    </main>
  );
}

export async function getStaticProps() {
  const res = await fetch("https://yesno.wtf/api");
  const yesOrNot = await res.json();
  return {
    props: {
      yesOrNot,
    },
  };
}
@aardani Data Cache is persisted in between build iirc, try removing the `.next` folder before exporting?
Philippine CrocodileOP
Thanks!
Yes, manually removing the .next folder works locally. I'm not sure how I could implement this workaround live
@Philippine Crocodile Thanks! Yes, manually removing the .next folder works locally. I'm not sure how I could implement this workaround live
you could add a path to revalidate the fetch data, live. But not sure if it could work on other places outside of Vercel
(I personally havent tested)
Philippine CrocodileOP
Thank you for the help. I'll try to search and keep you updated 🙂
@Philippine Crocodile Thank you for the help. I'll try to search and keep you updated 🙂
Ok I got your setup, in Next.js it's more common to keep a server around to be able to revalidate static pages on demand
here you are doing an export, so you have to do a full rebuild
you indeed seem to have an issue with Netlify/Next.js caching stuff across rebuilds which you don't want, so removing .next would work
you can probably craft a custom build command like "rm -Rf .next && next build" for instance
you'd want to reach out to your host support too
(totally personal opinion but I never had a good behaviour with Netlify + Next)
@Eric Burel you can probably craft a custom build command like "rm -Rf .next && next build" for instance
Philippine CrocodileOP
Thank you for the response!
Yes, this is the solution that I have implemented for now. I want to point out that it is a problem that also occurs locally and is not connected to Netlify. On your suggestion, I have decided to try both solutions: the static site on Netlify and incremental static regeneration on Vercel.
I will see if the costs are worth the advantages that can be obtained by using Next.js to its fullest potential 😅

Thank you for the help