vercel / next.js

The React Framework
https://nextjs.org
MIT License
127.01k stars 26.99k forks source link

Nextjs13 fetch stale while revalidate cache not working in edge runtime #52743

Open leo-cheron opened 1 year ago

leo-cheron commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000
    Binaries:
      Node: 19.8.1
      npm: 9.5.1
      Yarn: 1.22.17
      pnpm: 8.6.6
    Relevant Packages:
      next: 13.4.10-canary.8
      eslint-config-next: N/A
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 4.9.5

Which area(s) of Next.js are affected? (leave empty if unsure)

App Router

Link to the code that reproduces this issue or a replay of the bug

https://github.com/mrgnou/nextjs-issue-fetch-cache

To Reproduce

By implementing some dynamic route in our nextjs app dir application, we noticed random very slow TTFB on Vercel. By digging further, when the revalidation time of a fetch is reached, the page rendering will be blocked until the fetch cache is populated again (should be stale while revalidate).

To test it, I'm fetching a test route which delays the returned value by 3 seconds. revalidate is set to 10 sec, runtime to edge.

page.js

export default async function Home() {
    console.time('home: fetch date')
    const data = await fetch(`http${process.env.NODE_ENV === 'development' ? '' : 's'}://${process.env.VERCEL_URL}/api/date`).then(d => d.json())
    console.timeEnd('home: fetch date')

    return <>{data.date}</>
}

export const revalidate = 10
export const runtime = 'edge'

api/date/route.js

import {NextResponse} from 'next/server'

export const runtime = 'edge'
export const revalidate = 0

export async function GET (req: Request) {
    console.log("fetching date")

    await new Promise(resolve => {
        setTimeout(() => {
            resolve('promise resolved')
        }, 3000)
    })

    return NextResponse.json({success: true, date: new Date().toLocaleDateString('en-us', {
        weekday: 'long',
        year: 'numeric',
        month: 'short',
        day: 'numeric',
        hour: 'numeric',
        minute: 'numeric',
        second: 'numeric'
    })})
}

Describe the Bug

image

Some additional confusing data: Fetching takes less then 10ms even when the page rendering is blocked during revalidation, meaning the cache seems to be properly returned.

image

Expected Behavior

The fetch response should be returned as stale while revalidate and page rendering should be blocked only if cache has never been populated.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

Vercel

lakeesiv commented 1 year ago

Any updates on this?

siffogh commented 1 year ago

This could be related to #54193 , happy to help reproducing this if the example in this issue and linked one are not clear enough 🙏