next.js icon indicating copy to clipboard operation
next.js copied to clipboard

ISR cache issue on root page when using optional catch all routes

Open scpaye506 opened this issue 2 years ago • 1 comments

Verify canary release

  • [X] I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 Binaries: Node: 17.2.0 npm: 8.1.4 Yarn: N/A pnpm: N/A Relevant packages: next: 12.2.5-canary.4 eslint-config-next: 12.2.4 react: 18.2.0 react-dom: 18.2.0

What browser are you using? (if relevant)

not relevant

How are you deploying your application? (if relevant)

not relevant

Describe the Bug

The bug happens when using ISR with an optional catch all route at the root of the pages dir, like pages/[[...slug]].tsx, and when no root path is returned from getStaticPaths.

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

When hitting the root route http://localhost:3000/ the Cache-Control Response Header only shows up on the initial request, on all subsequent requests, the Cache-Control Response Header is gone, and the Response Header now always has a x-nextjs-cache: STALE.

The issue only happens on the root page, using any other url path, like http://localhost:3000/foobar works as expected.

This issue appears to have started with v12.2.1 and is not happening in v12.1.6

Expected Behavior

The Cache-Control Response Header should be present on every request for the root page.

Link to reproduction

https://github.com/scpaye506/isr-cache-issue

To Reproduce

Pull down reproduction repo.

  1. npm install
  2. npm run build
  3. npm run start
  4. open browser dev tools and then visit http://localhost:3000/ and inspect the response headers, if this is the first visit to the page you should see the Cache-Control: s-maxage=10, stale-while-revalidateheader
  5. refresh the page and inspect response headers again and the Cache-Control header is gone and the page is being regenerated on every request going forward.

scpaye506 avatar Aug 11 '22 14:08 scpaye506

I also ran into this issue recently, as a temporary fix you can instead define a catch all route with a single bracket, along with a predefined route for the index page reusing your exports from the dynamic route.

For example instead of using pages/[[...slug]].tsx

├── pages
│   └── [[...slug]].tsx

Use

├── pages
│   ├── [...slug].tsx
│   └── index.tsx

And populate index.tsx to export the same methods from your catch all route:

// pages/index.tsx

export { default, getStaticProps } from './[...slug]';

Obviously not ideal but hopefully helps others in the meantime.

Morsey187 avatar Nov 13 '22 19:11 Morsey187

Hey I think this lead me to solving the same issue, I didn't realize we weren't generating the homepage in getStaticPaths - seemingly fixes things when I do this.

For me, this was only an issue when using output: 'standalone',, not when running next start. I was having this issue on next 13.5.6.

@scpaye506 Thank you for this issue, I was tearing my hair out.

MartinDavi avatar Dec 20 '23 18:12 MartinDavi