Next.js ISR not working

team: iamsterdam
website: https://iamsterdam-redis-cache.netlify.app

I want to move to use Nextjs’ Incremental Static Regeneration instead of SSR for most of my pages (loaded from a CMS), but I cannot get it to work.

I have the following file structure set up: the file that’s using getStaticProps combined with getStaticPaths is located at pages/static-pages/[...slug]/index.js. getStaticProps correctly returns a revalidate property (set to 300 so it should be cached 5 minutes) and getStaticPaths returns the following:

 return {
    paths: [],
    fallback: true,
  };

This is because I want all the pages to not be generated on build time, but cached for 5 minutes after the first visit. I’ve set up some rewrites in next.config.js so, for example, https://iamsterdam-redis-cache.netlify.app/uit/agenda/eten-en-drinken is handled by the handler in pages/static-pages/[...slug]/index.js. I have checked to verify this is actually where it ends up with some console logs. Still I always get the server side rendered version of the page, which I know by the long loading times and the response headers that are always the same (most notably the x-nf-render-mode: ssr, which should be x-nf-render-mode: odb ttl=300).

In the Netlify docs Netlify claims to have full support for ISR (using the netlify-plugin-nextjs), but does it? Am I missing something?

Hi @floris10hove, Even though I have experienced this same issue before, I cannot tell for sure what might be causing the ISR not to work at your end.
I also noticed that when you host Next.js on Netlify with ISR, no matter the revalidate value you set, it always defaults to 1 minute (60 seconds).

For me once I set fallback to “blocking” the ISR worked but the revalidate still defaulted to 60 seconds.
Kindly set fallback to “blocking” and also set revalidate to 10 to see if it will work.

Also note that ISR defaults to SSR on development.

Thanks.

Thanks for your reply! I have set the fallback to “blocking” and the revalidate time to 10 seconds, but nothing has changed unfortunately. It’s really weird because on build it indicates that path /static-pages/[...pages] will be SSG using getStaticProps…


Hi @floris10hove, thanks for your feedback as well.
If possible can you share a code snippet of your /static-pages/[...pages] file for me to help with the debugging.

Thanks.

Sure. I had to change it a bit because it concerns a lot of files, but basically the file is like this. getPage is just a function that fetches data from a CMS.

import { getPage } from "~utils/cms/getPage";
import withLayout from "~utils/withLayout";
import DynamicPage from "~modules/DynamicPage";

export const getStaticPaths = async () => {
  return {
    paths: [],
    fallback: "blocking",
  };
};

export const getStaticProps = async (context) => {
  const response = await getPage(context);

  if (!response || Object.values(response).length === 0) {
    return {
      notFound: true,
    };
  }

  return {
    props: response,
    revalidate: 300,
  };
};

export default withLayout(DynamicPage);

After some experiments I think I have found the problem: ISR does not work when the page is part of a rewrite (in config.next.js). I do think this should actually be possible with NextJS, but apparently Netlify does not support this.

When I just create folders like this pages/uit/agenda/[...slug] and then go to, for example, Restaurants, ISG does work.

I would still like to hear from someone at Netlify whether this is expected behaviour or if this is considered a bug?

Hi @floris10hove, thanks for sharing your findings about the reason why ISR does not work in your case.

At this point all I can say is that Next.js version 13.x.x is fairly new and not stable. Therefore bugs and problems should be expected.

I will tag @fool on this post. He could provide any insights or if has any thoughts on the reason why ISR does not work when the page is part of a rewrite and hosted on Netlify.

Thanks.

I don’t think this is a Netlify issue. Checking your latest build, I see this:

3:13:25 PM: Route (pages)                                    Size     First Load JS
3:13:25 PM: ┌ ● /                                            3.1 kB          215 kB
3:13:25 PM: ├   └ css/ea98323f7a22b762.css                   1.96 kB
3:13:25 PM: ├   /_app                                        0 B             150 kB
3:13:25 PM: ├ ● /[...pages] (ISR: 300 Seconds) (222709 ms)   290 B           322 kB
3:13:25 PM: ├   ├ /en/whats-on/kings-day (7607 ms)
3:13:25 PM: ├   ├ /en/live-work-study (7602 ms)
3:13:25 PM: ├   ├ /en/i-amsterdam-store (7432 ms)
3:13:25 PM: ├   ├ /en/explore (7371 ms)
3:13:25 PM: ├   ├ /en/whats-on/concerts-and-gigs (7335 ms)
3:13:25 PM: ├   ├ /en/conventions (7235 ms)
3:13:25 PM: ├   ├ /en/amsterdam-and-partners (7093 ms)
3:13:25 PM: ├   └ [+93 more paths] (avg 1839 ms)
3:13:25 PM: ├ ○ /404                                         2.44 kB         176 kB
3:13:25 PM: ├ ● /500                                         2.45 kB         176 kB
3:13:25 PM: ├ λ /api/articles                                0 B             150 kB
3:13:25 PM: ├ λ /api/breadcrumbs/[locale]                    0 B             150 kB
3:13:25 PM: ├ λ /api/cache/invalidate                        0 B             150 kB
3:13:25 PM: ├ λ /api/mail/venue-finder/request-quote         0 B             150 kB
3:13:25 PM: ├ λ /api/shop/customer                           0 B             150 kB
3:13:25 PM: ├ λ /api/shop/payment/checkout                   0 B             150 kB
3:13:25 PM: ├ λ /api/shop/payment/status/[encryptedOrderId]  0 B             150 kB
3:13:25 PM: ├ λ /api/shop/payment/webhook                    0 B             150 kB
3:13:25 PM: ├ λ /api/shop/products                           0 B             150 kB
3:13:25 PM: ├ λ /api/shop/products/[productId]               0 B             150 kB
3:13:25 PM: ├ λ /api/stats                                   0 B             150 kB
3:13:25 PM: ├ λ /api/upcoming-events                         0 B             150 kB
3:13:25 PM: ├ λ /api/upcoming-events/[locationId]            0 B             150 kB
3:13:25 PM: ├ λ /api/venues                                  0 B             150 kB
3:13:25 PM: ├ λ /design-system                               1.12 kB         175 kB
3:13:25 PM: ├   └ css/75f17fd25bf46003.css                   816 B
3:13:25 PM: ├ λ /dynamic-pages/[...pages]                    301 B           322 kB
3:13:25 PM: ├ λ /favourites                                  2.04 kB         197 kB
3:13:25 PM: ├   └ css/d8444e3abd4a2f76.css                   1.06 kB
3:13:25 PM: ├ λ /search                                      3.59 kB         199 kB
3:13:25 PM: ├   └ css/b2d372a0831aa148.css                   1.27 kB
3:13:25 PM: ├ λ /shop/checkout/[preprId]                     8.12 kB         187 kB
3:13:25 PM: ├   └ css/e6776fad45fa1760.css                   5.23 kB
3:13:25 PM: ├ λ /shop/products/[preprId]                     3.87 kB         216 kB
3:13:25 PM: ├   └ css/eea560e80ab1b02b.css                   1.69 kB
3:13:25 PM: ├ λ /shop/return/[preprId]/[orderId]             4.11 kB         216 kB
3:13:25 PM: ├   └ css/8c1474c758eb1ae3.css                   1.12 kB
3:13:25 PM: ├ λ /sitemap.xml                                 239 B           150 kB
3:13:25 PM: ├ λ /venue-finder/[preprId]                      8.37 kB         223 kB
3:13:25 PM: ├   └ css/53bf05facba18b72.css                   2.01 kB
3:13:25 PM: └ λ /venue-finder/[preprId]/[slug]               23.8 kB         239 kB
3:13:25 PM:     └ css/3bac57b6598a9694.css                   4.29 kB
3:13:25 PM: + First Load JS shared by all                    154 kB
3:13:25 PM:   ├ chunks/framework-73b8966a3c579ab0.js         45.2 kB
3:13:25 PM:   ├ chunks/main-9c0e14d9575d6a34.js              36.6 kB
3:13:25 PM:   ├ chunks/pages/_app-3342a8362e53f8a6.js        65.9 kB
3:13:25 PM:   ├ chunks/webpack-659dbb4955eabeed.js           2.12 kB
3:13:25 PM:   └ css/2c774cb5b81ba3f6.css                     3.68 kB
3:13:25 PM: ƒ Middleware                                     27.7 kB
3:13:25 PM: λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
3:13:25 PM: ○  (Static)  automatically rendered as static HTML (uses no initial props)
3:13:25 PM: ●  (SSG)     automatically generated as static HTML + JSON (uses getStaticProps)
3:13:25 PM:    (ISR)     incremental static regeneration (uses revalidate in getStaticProps)

Next.js is not marking any page as ISR. This is during the build stage, that’s entirely handled by Next.js and Netlify is not doing anything at that point. So there appears to be something incorrect in the way you’ve set things up which is why Next.js is not treating any page as ISR.

Thanks for your reply @hrishikesh . I don’t think what you’re saying is true, because in the logs you added above it does say that [...pages] uses ISR:

I’ve written a new approach which does seem to work for most pages: I’m using the catch-all [...pages] directory for ISR instead of rewrites. Unfortunately another problem arises: for pages that do need query params on the server side I have added rewrites to the nextJS config that uses SSR. I have verified that this works correctly locally but not on Netlify.

I’ve concluded that NextJS rewrites + ISR for those pages is not supported on Netlify. That’s fine because I have a new approach which does make ISR working (as seen in your deploy log and verified on my site).

This new approach does reveal a new problem, but since it’s a problem that isn’t directly related to the old one, I’ve created a new support forums ticket with a clear explanation and example of the problem here: NextJS rewrite not working with SSR.

Thanks for your help anyway!

Oh sorry, I missed that line.

In that case, do you think you can provide a minimal reproduction of the setup that was not working? That is, with rewrites + ISR? We can pass that to devs so they can verify and try to support that configuration as well.