NEXT.js ISR remove static page

Viewed 1214

I have a little problem with the ISR. I have the revalidate prop equal 1s like here

export async function getStaticProps({ params }) {
  const data = await client.getEntries({
     content_type: "product",
    "fields.name": params.slug,
  });


  if (!data.items[0]) {
    return {
      notFound: true,
    };
  }
  return {
    props: {
      article: data.items[0],
      revalidate: 1,
    },
  };
}

When I create product in Contentful, the page is created as I expected. When I want to entry to page that doesn't exist I get 404 error as expected. Problem starts when I change something in Contentful in existing product or I delete it.

When I delete the product in Contentful, the list of products in the products page is updated and the product disappears but I can still entry in page of that product. Also when I rename the product name the list of products is updated but I still can entry to the earlier page name.

Is there any solution to solve this problem?

getStaticPaths

export async function getStaticPaths() {
  const data = await client.getEntries({
    content_type: "product",
  });

  return {
    paths: data.items.map((item) => ({
      params: { slug: item.fields.name },
    })),
   fallback: true,
 };
}

Product page

const Article = ({ article }) => {
  const router = useRouter();

  if (router.isFallback) return <p>Loading...</p>;

  return (
    <div>
      <h1>Hello! {article.fields.name}</h1>
      <Link href="/about">
        <a>Back to about!</a>
      </Link>
    </div>
  );
};

EDIT When I change product name from "product77" to "product7" in Contentful after revalidate static page in my build for product77 still exist and I still can entry to that page. enter image description here

Shouldn't it be removed after revalidation?

1 Answers

Removed pages can't be deleted, but served with a 404 instead using On-demand Revalidation, if getStaticPaths and getStaticProps are configured accordingly.

// /pages/blog/[...post].jsx

function Post({ postData }) {
    return (
        // ...
    );
}


export async function getStaticPaths() {
    const res = await fetch("https://.../posts");
    const posts = await res.json();

    // Prerender paths during build
    const paths = posts.map((post) => ({
        params: { post: post.id },
    }));

    return { paths, fallback: "blocking" };
}


export async function getStaticProps(context) {
    const res = await fetch(`https://.../posts/${context.params.post}`);
    const postData = await res.json();

    if(!postData){
        // The page doesn't exist in the CMS, return notFound to trigger a 404
        return{
            notFound: true,
            revalidate: 30
        }
    }

    // Return page props
    return {
        props: {
            postData,
        },
        revalidate: 30, 
    };
}

The main takeaway from the above code is:

  • You can pre-render paths in getStaticPaths
  • getStaticPaths must use "blocking" or true as the fallback value
  • Handle unknown paths inside getStaticProps (thanks to fallback). If the page doesn't exist in the CMS, return notFound: true triggering the 404 page

Then, using the On-demand revalidation approach in a webhook:

// /pages/api/revalidate-post.js

export async function handler(req, res) {
    try {
        const reqBody = JSON.parse(req.body);
        await res.revalidate(`/${reqBody.path}`);
        return res.json({ revalidated: true });
    } catch (err) {
        return res.status(500).send("Error revalidating");
    }
}

The res.revalidate(/${reqBody.path}) invokes a fresh evaluation of a page using the logic from getStaticProps.

Now, if somebody would delete the page in the CMS, and trigger the above revalidation webhook handler for the deleted page path, then the path serves a 404 page instead of the original page.

The page itself, however, is not deleted from the disk.

Related