What Next.js doesn't tell you about caching...

Sdílet
Vložit
  • čas přidán 23. 07. 2023
  • In this video we discuss some issues and confusion around how page and data caching works for NextJS, and we talk about the distinction between server and client caching and the settings which affect both. We also discuss the behavior of the next js Link component, how prefetch affects caching behaviors, and finally the distinction between soft vs hard navigation.
    Github Issue about stale pages: github.com/vercel/next.js/iss...
    Client cache semantics relating to prefetch: github.com/vercel/next.js/pul...

Komentáře • 70

  • @mariusespejo
    @mariusespejo  Před 11 měsíci +11

    Just wanted to clarify: when I was trying to demo the 30s ttl, I should not have hit refresh just before (which might’ve already cleared the cache). I meant to show that clicking quickly shows cached data, but after 30 seconds it gets you a new one. Sorry I totally messed up 😂 but I hope it makes sense!

    • @AldisSv
      @AldisSv Před 6 měsíci +1

      Thanks Marius for clearing this up. Btw, I learn't these 30 seconds the hard way, just clicking back and forth with tag, and seeing that suddenly it starts behaving dynamically after some time. It started to fetch data on server side on each navigation. I just dont understand why it's not working like that right from the beginning, why exactly we need to wait those 30 seconds...

  • @WebDevCody
    @WebDevCody Před 11 měsíci +18

    yup, I ran into this a while back and it's very annoying. The only fix I found it to add a client component on the page you know should be fresh data each time, and put a router.refresh() inside a useEffect on mount.

    • @EnesKab
      @EnesKab Před 2 měsíci +1

      Dude ! I am pulling my hair for the last 5 hours and your comment did the trick finally ! Thank you !

  • @divinelogik
    @divinelogik Před 4 měsíci +2

    Jesus dude. This is exactly what I was looking for. I legit tried all 5 strategies for blowing away the cache (no-store, force-dynamic, force-no-store, revalidate=0, React unstable cache), and to find that I was affecting only the server-side cache was mind-boggling. But this makes total sense. Short story: use to kill it entirely.

  • @dawid_dahl
    @dawid_dahl Před 11 měsíci

    Thanks so much for making a video trying to clarify this. Very important stuff. 🙏🏻

  • @MMEDHAT1910
    @MMEDHAT1910 Před 10 měsíci

    Hello Marius, your videos are great and of huge benefit. I started learning nest js by watching your videos. Keep going ❤️❤️

  • @iukeay
    @iukeay Před 11 měsíci

    Thanks for your amazing videos!

  • @_bouwer
    @_bouwer Před 11 měsíci

    Oh my gosh, thanks for this. Hopefully the docs get updated soon.

    • @mariusespejo
      @mariusespejo  Před 10 měsíci +1

      just an hour ago actually they posted a response/discussion on the github issue, where they fully explain why this 30s thing exists. It’s probably the best explanation we’ll get. I might cover it in a follow up video if I get some time

  • @oscarresonable2008
    @oscarresonable2008 Před 10 měsíci

    Very insightful. I'm actually scratching my head all day long wth is going on 😂😂. As always, Thanks Marius. Keep going brother.

  • @berlatoy
    @berlatoy Před 7 měsíci

    Thank you so much for this explanation bro

  • @ayushjain7023
    @ayushjain7023 Před 11 měsíci +4

    To fix it just create a client component returning null, with router.refresh() inside a useeffect with empty dependency array, and add it in a server component, boom 💥 it will work

    • @mariusespejo
      @mariusespejo  Před 11 měsíci +6

      Right, however It’s more of a hack than a fix. Nextjs needs to create a way to opt-out

  • @AlfonsusAC
    @AlfonsusAC Před 11 měsíci +6

    So im not the only one that is having trouble understanding this

  • @noeldolan518
    @noeldolan518 Před 6 měsíci +1

    Great video! :). BTW what is the flow diagram UI tools you're using @ 4:00?

  • @SamTipton
    @SamTipton Před 8 měsíci

    I've only been learning next for just a week now, but this caching behavior makes sense to me because were doing SSR by default. Would have been interesting to see what would happen if you made it a client component.

  • @bricelechatellier
    @bricelechatellier Před 11 měsíci

    Thanks for covering this in details, does this happen to layouts as well? I have a layout handling user authentication with cookies and redirecting if the user is signed in but I get into a redirect loop after signing out as it's cached on the client. Any ideas how to fix the problem?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      Layouts do not re-render on navigation, that’s by design and is documented. You might need to force a router.refresh() in that case

    • @bricelechatellier
      @bricelechatellier Před 11 měsíci

      @@mariusespejo Thanks, makes sense, I can do a router refresh on sign out but if my session expires I’m stuck with a stale state. Looks like I’m mis-using layout and need to wrap logic in pages, correct?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      Well in my mind you have to go to the server in some way, e.g. via a request to see if the session is still valid, and the request(s) should probably respond with maybe status 401/403. The client should then be setup to react to any request failing with that status and perhaps route to login screen and refresh

  • @sr-juhahn
    @sr-juhahn Před 11 měsíci +1

    I feel like exactly this problem is currently ruining my mental model of authentication with nextjs. I integrated supabase, into my nextjs middleware to check if the user has a valid session before routing to protected sites and sending the user to login if not. This works great, until the user clicks 'logout' on a protected page - at which point the protected page was loaded into the client cache and after that the user is still able to access the protected page, because the nextjs link and rounter will do a soft routing and my server middleware never get's another call if the user is allowed to go to the protected page and cannot redirect.
    Tried 'force-dynamic' on the server and also tried to manually set the header 'Cache-Control: no-store' to try to convince the browser to send another request to my middleware. Any suggestions for this kind of problem?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      They actually released new docs about the caching shortly after this video. The client-side cache that I talk about in the video is officially called “Router Cache”
      You can’t opt out of it unfortunately but they do give some options to invalidate. In your case you either need to router.refresh() on sign-out or you can use a server action to either use revalidateTag/revalidatePath (e.g. if you tagged your protected fetch calls), Or if you use cookies for auth, run cookies.delete() in a server action
      Either of those should do the trick but you’ll have to test out which one works best. If you’re trying to invalidate the server-side Data Cache in addition to the client Router Cache I think you have to use the revalidateTag/Path. Hope that helps
      nextjs.org/docs/app/building-your-application/caching#invalidation-1

  • @LuisJimenez-uh1zx
    @LuisJimenez-uh1zx Před 11 měsíci

    Hello, I have a simple application in nextjs and mongoDB, when I'm in development it does the crud fine, but when I deploy in vercel, it's like the front doesn't refresh the data, but it does manipulate the data, I don't understand why this behavior , even so, reloading the page does not work, it is as if at the time of doing the build it saved the data from this moment and only displayed that.

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      The caching behavior for server-side only happens in prod I think, not in local. Depending on your use case you might need to set revalidate to how often you want it to, or use force-dynamic

    • @LuisJimenez-uh1zx
      @LuisJimenez-uh1zx Před 11 měsíci

      @@mariusespejo thanks

  • @j_pestana
    @j_pestana Před 11 měsíci +1

    I knew about the issue, but I haven't had any problematic situation because of it so far on the little projects I'm playing with.
    Thanks man for this huntdogs investigation work, and clarification. Great job on explaining. I really had no clue about that "Meta-caching" (Server & Client) that was going on under the hood.
    I don't see any easy fix to this though...😢
    Is there an alternative to the Link component that could help?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci +3

      So to be fair I think 30s is small enough that it probably isn’t that big of a problem for most use cases. I think you can also use the native anchor tag instead of Link which would always go back to the server. Also you could manually call router.refresh() on mount … but yeah all the options are a little hacky. If the 30s (or 5min on prefetch true) doesn’t affect you then I’d just leave it. The problem is mostly for cases where you absolutely cannot get away with showing stale data

  • @iPankBMW
    @iPankBMW Před 7 měsíci

    Thank you for this video! I went immediately to Nextjs docs and red the latest instructions - now they are mentioning it. And they say there is no way to opt out of the default 30 seconds server component payload cache (cliend-side/router-cache). That terible. So there is no way we can use server components for data fetching if you always need latest data from backend… So useless.. Gues for latest data from backend we still need to stack to client side components…

  • @tifactlong7431
    @tifactlong7431 Před 3 měsíci

    How about in page router? All I see is app router revalidating route but I need also it in page router

    • @mariusespejo
      @mariusespejo  Před 3 měsíci +1

      This caching behavior is for app router only

  • @liu-river
    @liu-river Před 11 měsíci +4

    Appreciate the explanation. Any chance you could do a video on deep dive on Next js caching and revalidation including, data cache, route cache, etc?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci +2

      Yeah I’ve actually been learning a lot about it in my own projects, I can definitely cover that in more detail. Have you seen the new docs for it? It didn’t exist at the time of this video

    • @liu-river
      @liu-river Před 11 měsíci

      @@mariusespejo I have, it's not very beginner friendly. I kinda understand it but it gets quite complicated. Maybe it's one of those things that you will have to play with a lot and try out all different scenarios to fully grasp.

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      Yeah I agree, I’ve had to read it multiple times to be honest and parts of it is still confusing haha

    • @liu-river
      @liu-river Před 11 měsíci

      @@mariusespejo yeah, quick question though do you know if server cache actually works in dev mode, or is it production only?

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      “Data cache” (server) I’m pretty does work in development because when I call fetch server-side the terminal logs tell me if they are cache HIT or MISS. If you look in the .next folder you also will see cached data in there. Although I have seen people saying cache doesn’t work in dev mode and what’s tricky is there are multiple caches right, and idk what people are talking about exactly. The docs does say however that link prefetching only works in production, and prefetching affects the “Route Cache” (client) behavior.

  • @ilijanl
    @ilijanl Před 10 měsíci +2

    Great video and great explanation. I guess they do aggressive caching because of the lamda's cold starts/slow execution which makes the app slow otherwise. In my opinion caching (on every level) should always be opt-in. Something with "pre-optimisation is root of all evil"

  • @kishansripada3392
    @kishansripada3392 Před 11 měsíci

    experienced this issue myself. this clarifies so much! what's the best way right now to work around it? right before navigating to another page using router.push(), i added a router.refresh() but this doesn't seem to work.

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      You can use router.refresh() on mount of the page you’re navigating to, like in a useEffect for example. Or you can use old school html tags to force it to go back to the server
      Basically all of the solutions are hacky, hopefully they’ll provide a way to opt out. Currently the newest docs literally say you can’t opt out and people are mad haha

    • @jaeken
      @jaeken Před 10 měsíci

      @@mariusespejo cant do router.refresh() in a server compontent tho right?

    • @mariusespejo
      @mariusespejo  Před 10 měsíci +2

      Right, it’s for client, which is where the router client cache is that we’re trying to invalidate. Btw next team did make a proposal for a fix that will let you configure the staletime but it might take them a while to implement

  • @ibrahimo0682
    @ibrahimo0682 Před 5 měsíci

    just use

    • @mariusespejo
      @mariusespejo  Před 5 měsíci

      You can but you also lose the optimizations that the Link component provides

  • @BimaAulia-fz1yt
    @BimaAulia-fz1yt Před 3 měsíci

    Which next js version are you using?

    • @mariusespejo
      @mariusespejo  Před 3 měsíci

      Not sure what I was using here, but the github ticket for this is still open so it’s still relevant in the most recent version today

  • @ausername4meplease
    @ausername4meplease Před 4 měsíci +1

    Thank you for the explaination but, no solution :(

  • @Psych134
    @Psych134 Před 6 měsíci

    Hey buddy, as of today is there any fix from nextjs team on this issue or do we still have to use work arounds?
    Anyway, great video!

    • @mariusespejo
      @mariusespejo  Před 6 měsíci

      Not really (last I checked), there is a massive open discussion about this if you want to know where’s it at: github.com/vercel/next.js/discussions/54075
      But it really is a massive thread, but basically you still can’t configure this or opt out

    • @Psych134
      @Psych134 Před 6 měsíci

      @@mariusespejo thank you

  • @kaisian4940
    @kaisian4940 Před 11 měsíci

    10:37, by right you hit refresh should get the new random value already no need wait 30s

    • @shabadouwilou
      @shabadouwilou Před 11 měsíci

      thats what i was tinking but maybe i miss something

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      Yeah I now realized I made that demo more confusing lol. The point was to show that prior to waiting you see cached, after 30 seconds the number is updated. I shouldn’t have refresh, good catch!

  • @AshishKumar-ft6wv
    @AshishKumar-ft6wv Před 4 měsíci

    😢😢 is the only option i guess

  • @izumiosana
    @izumiosana Před 11 měsíci

    honestly cache revalidation is one of the hardest thing in computer science.

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      Yup but it’s even worst when you can’t opt out of it, or even control when it revalidates

  • @nikako1889
    @nikako1889 Před 7 měsíci

    is it fixed on nextjs 14?

    • @mariusespejo
      @mariusespejo  Před 7 měsíci

      Nope. You still can’t opt-out as of today. But there is an open ticket for it with a proposal from the team

    • @nikako1889
      @nikako1889 Před 7 měsíci

      @@mariusespejo thanks for answer.

  • @shabadouwilou
    @shabadouwilou Před 11 měsíci

    why hit refresh lol

    • @mariusespejo
      @mariusespejo  Před 11 měsíci

      I just realized what you meant 😂 yeah I totally messed that up haha

  • @kumarvishalben
    @kumarvishalben Před 11 měsíci +1

    super confusing

  • @oopss794
    @oopss794 Před 10 měsíci

    many bad decisions are done in next js 13 ,

    • @mariusespejo
      @mariusespejo  Před 10 měsíci

      Give it time, community will iron it out

    • @oopss794
      @oopss794 Před 10 měsíci

      it's almost a year now since the conference

  • @felipefreire5245
    @felipefreire5245 Před 11 měsíci

    Tthis is the worst thing i have ever seen Vercel do

    • @mariusespejo
      @mariusespejo  Před 11 měsíci +1

      They did just recently comment on the github issue that they are looking at all the feedback and will address it somehow. Hopefully a better resolution in the future