vercel / next.js

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

Caching doesn't work #46221

Open macienrique opened 1 year ago

macienrique commented 1 year ago

Verify canary release

Provide environment information

Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 22.3.0: Thu Jan 5 20:48:54 PST 2023; root:xnu-8792.81.2~2/RELEASE_ARM64_T6000 Binaries: Node: 14.18.1 npm: 6.14.15 Yarn: N/A pnpm: N/A Relevant packages: next: 13.1.6 eslint-config-next: 13.1.6 react: 18.2.0 react-dom: 18.2.0

Which example does this report relate to?

ssr-caching

What browser are you using? (if relevant)

Opera GX

How are you deploying your application? (if relevant)

next start

Describe the Bug

Hi everyone, when I deploy this to Vercel it works as expected. However, when I run the production build locally, it doesn't work. Is there something I'm missing? Thanks in advance!

Expected Behavior

I expect the html to be cached in my browser and not hit the production server running locally (with npm run build && npm start)

To Reproduce

Adilio848 commented 1 year ago

Não dar pra ver os vídeos no tik toq como eu faço pra ver

icyJoseph commented 1 year ago

When you refresh the page, often browsers interpret that as: "the user thinks the data is stale, let's get new data" - You did not provide a repository though, so I guess you are experiencing this.

What if you use the back button and then forward button from the browser? Then the browser should show the same HTML.

This post from the Chromium team sheds some light onto this, https://blog.chromium.org/2017/01/reload-reloaded-faster-and-leaner-page_26.html:

Users typically reload either because a page is broken or the content seems stale. The existing reload behavior usually solves broken pages, but stale content is inefficiently addressed by a regular reload, especially on mobile [...] To improve the stale content use case, Chrome now has a simplified reload behavior to only validate the main resource and continue with a regular page load. [...]

Though you use Opera GX, so it might not be the same behavior.

If you provide a repository link, I can help look further, maybe there's a bug, who knows.

macienrique commented 1 year ago

Hi @icyJoseph , thanks for the reply. the repo is https://github.com/vercel/next.js/tree/canary/examples/ssr-caching. Just tried it out in Google Chrome and it has the same behavior, every refresh does show a different time. However, when this is deployed to vercel, every refresh DOESN'T show a new time. Just wanted to see what needs to be done so this behavior (vercel's) is replicated locally as well.

If I use the back and forth, the time doesnt change, ever. and it should with the max age given.

icyJoseph commented 1 year ago

From the "going to production" page, https://nextjs.org/docs/going-to-production#caching:

Your deployment provider must support caching for dynamic responses. If you are self-hosting, you will need to add this logic yourself using a key/value store like Redis. If you are using Vercel, Edge Caching works without configuration.

I'd speculate that this is the browser behavior I described initially. During development, there's no cache layer, same if you do next build and next start locally, the when the user refreshes the page, the browser interprets that as the user wanting new data, so it overrides the stale-while-revalidate call.

When you deploy to Vercel, even if the browser does that, it hits the Vercel CDN, and there it goes back to the client, skipping a server hit. You can see the network request, it probably has a header [X-Vercel-Cache](https://vercel.com/docs/concepts/edge-network/caching#x-vercel-cache).

macienrique commented 1 year ago

ah I see, so theres no way to force your own browser to cache this html like it does with js/css assets where it gets them from memory/disk cache?

icyJoseph commented 1 year ago

I know its super weird. It always caches me by surprise.

To improve the stale content use case, Chrome now has a simplified reload behavior to only validate the main resource and continue with a regular page load

I guess since reading data should be idempotent, and not break CQS, the caching on the browser is more of an optimisation, rather than an enabler. If the main resource points still to the same JS/CSS that's already on disk, the browser uses those.

Screenshot 2023-02-23 at 08 57 50

Since the GSSP main html page is SSR rendered the Date changes, but it still points to the same JS/CSS made at build time, so those come from disk.

sjc5 commented 1 year ago

It always caches me by surprise.

I apologize for this off-topic response, but this pun is just too perfect to go unnoticed. Amazing work here.