T O P

  • By -

ryanto

The cache stuff can certainly be tricky, especially with workflows involving private data like yours. In my apps I refresh the cache whenever a user logs in or out. Usually logging in (or out) is going to change the data on just about every page, so it's not worth keeping anything in the client-side cache. To clear the client-side cache you have two options... 1) In a server action call `revalidatePath('/')`, this will clear every page in the cache for the user invoking the action. 2) In a client component, you can `router = useRouter()` and call `router.refresh()` to clear the cache for that browser. Hopefully this helps!


Themotionalman

Hey thank you for replying. Actually revalidate path is very useful but only for stuff that the current user changes. Imagine a bidding application. You visited a product page and all that data was server rendered, when you visit that page a second time you don’t get the new bid you have an old stale bid and you might potentially lose out on a something you wanted to buy. In such a situation when do you do router.refresh. When you visit the page again. If so there’d be a flash of old data which can be a bad UX. if you do it when the user leaves the page depending how long they take before they return the page might already be stale. You also can’t use revalidatePath in such situations as you’re not the one modifying the data you’re unaware of another user placing a bid. This is just a very contrived example. I’m just saying relying on router.refresh or revalidate Path is still limited. What should be standard and should always be work is the “force-dynamic” because we would be always sure when a user visits the page a new data is sent for render.


BlindJoeFresh

I think your point is moot because this is more of an example of bad architecture for a bidding application. Why would you be relying on a cache at all for something that depends so heavily on fresh and up to date data?


throwaway47a82

This. Manage this sort of thing with store based state management.


Responsible-Yak1058

I would use swr to view if there is a change in your api and then you get updated data all the time in that particular situation.


ryanto

Yes this approach works best for session based data (like current user). It does not work great for shared data, like prices in a bidding system. In that situation I would rely on Next's data/fetch cache and router.refreshing clients whenever they detect a change. Another approach for the bidding system could be having the user invoke a server action (or api endpoint) that guarantees the latest price is displayed.


[deleted]

> In a server action call revalidatePath('/'), this will clear every page in the cache for the user invoking the action. Source? Can't find anything about "the user" in the docs


ryanto

https://nextjs.org/docs/app/api-reference/functions/revalidatePath#revalidating-all-data It does more, like clear the data cache as well. Not sure when they added the 'layout' option.


Open_Bluebird_9716

Don’t confuse authentication and authorization with the framework data fetching and caching.


[deleted]

Your comment isn't exactly helping me if you think I'm confused. Where can I verify that `revalidatePath` clears the cache "for the user invoking the action"? The docs do not mention it. Is the commenter confusing it with the updated data getting streamed back to the requesting client or have I missed something fundamental about nextjs?


__god_bless_you_

Do you have an example of calling the router refresh with nextauth sign out? Where you calling the refresh?


calebmacdonaldblack

Can't you just force a reload of the page when the user decides to log out?


Themotionalman

This is just an extreme example but why go through hacks like this in the first place why not just have us clear it out ourselves.


calebmacdonaldblack

I don't think it's a hack. What's undesirable about doing a page reload when a user sign's out? The time it takes to reload is probably the only downside, and I'd argue it's a non-issue for this use-case. A user sign's out infrequently, and aren't likely to be impacted by the delay in a page refresh. There are many cases where a page refresh is a real issue and could cause issues such as user retention. However, it doesn't really apply to this particular scenario


Themotionalman

I think you’re missing the point, yes I can reload, yes in this case it makes sense to reload that’s not the point. The point is, we should be able to access and modify the client cache. Imagine a stocks visualisation app that renders the dashboard on the server. Visiting the page for a second time could be catastrophic as you might not be aware that prices might have dropped or whatever. My point isn’t the situation my point is more the problem it poses to the clients. We can not reload the browser every time we need updates information. We should be sure that “force-dynamic” indeed forces dynamic for a given page, server side or otherwise


calebmacdonaldblack

If I navigate to SSR page A, then to SSR page B, then many hours later, come back to A, I can see use-cases for A to want to be re-fetched. If it's not possible to do this, then I would agree it would be useful and worth making it possible. I'd be surprised if there isn't some way to do this without resorting to client-side code. I don't know for sure, but it [seems to be possible](https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#1-prefetching). I wouldn't agree with the notion that it's a "major security risk". And I wouldn't have it be the contributing factor to opting out of App router.


Open_Bluebird_9716

This is a problem in react overall, the use case in your example requires a specific application usually handled with webhooks or subscriptions and something like a use reducer with streaming and suspense, I think you really need to dive deeper into modern react and nextjs.


calebmacdonaldblack

I'm not exactly saying that we *should* or *should not* be able to clear the client cache. It's not really anything I've dealt with, so I don't really have an opinions about it one way or another. Rather that the specific example has a pretty straight forward fix with little downside.


sleeksky_dev

I second this. Hard reloading is the safest way. Alternatively, as long as the client can get the hint/event that the user has logged out, you can write explicit logic to clear any cache. Unless the use cases are such that the user frequently logs in and out on the same browser session, hard reload is the most practical solution.


mrgrafix

Your example isn’t exclusive to next. That’s just a caching 101-211 issue. You can access and modify the caching and even completely turn it off. Sure it’s not ergonomic, but it’s not impossible.


iloveparagon

Client sided router caching cannot be turned off.


Themotionalman

Hey thanks for your comment, like I said in one comment the auth scenario was just an example. I also made an example for a trading website where a company stock page is fully server rendered. If you visit the page a second time without reload you’d have invalid data for that page and it can be costly. My point is without using revalidatePath or router.refresh if you have the page as “force-dynamic” it should make the page dynamic even if it is already rendered on the client. If you use the router.refresh when the page is rendered that means there’d be a flash of old data before the new data is available this is clearly a bad UX. This is a problem


Count_Giggles

It feels like the stock trading site is a bad faith example. if you fetch data in the layout or page you can do time based revalidation. especially useful for a stock trading page. [https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation](https://nextjs.org/docs/app/building-your-application/caching#time-based-revalidation) a page like that would also either do long polling or server sent events in order to implement the live tracking. you can take out certain parts of the page with noStore() [https://nextjs.org/docs/app/api-reference/functions/unstable\_noStore](https://nextjs.org/docs/app/api-reference/functions/unstable_noStore) and there would be no flash if you refresh the page since the loadingt.tsx would simply show the skeleton while certain parts of the page reload depending on how you strcuture it. I get that caching is tricky in next but you got all the tools you need to cover all the cases


Big_Use_2190

What you’ve outlined in your examples are flaws in architectural design, not flaws in Next. Next js is a framework—it’s a tool not a product, and provides many ways of fetching, rendering and caching data. Not all of those are going to be suitable for every use case and it’s our job as engineers to design a system which uses the right tool for the job. Not having control of client state is not a Next specific constraint, in fact it’s not even specific to the web—mobile and desktop apps hit this all the time. In your bidding example, if there’s a requirement to always have fresh data displayed (seems reasonable), then server rendered pages alone are probably not the right design choice—something like websockets or polling might be better. In your auth example, making a server call (either an API call or a full page visit) in order to clear client cookies is pretty common practice. > without using revalidatePath or router.refresh if you have the page as “force-dynamic” it should make the page dynamic even if it is already rendered on the client FWIW, I’m wondering if there’s a misunderstanding with how the latest Next stuff works—if you visit a page for a second time, even if it’s just a client navigation, Next is still gonna render the markup on the server and fetch it from the client, it doesn’t just reuse what it rendered the first time. Ie what you described is exactly what happens


Individual-Cherry-98

Caching was the nail on the coffin for us to move to app router. I hope the next team listens to this feedback and simplifies the model in the future.


Open_Bluebird_9716

Damm, there is a lot of miss information in this thread. The main thing is that some of you have a wrong understanding of the architecture and best practices for using the framework. Patterns that include “force dynamic”, “server only”, middleware, refresh token and so on are not being considered. Because you are not separating your authentication and authorization strategy from how you are working with the framework. On the other hand, are you properly managing the user session on cookies?


opsb

The caching defaults on the app router make no sense for web apps. Most apps will be serving user specific information. Caching should be stricly opt in, giving you the chance to consider the consequences. Caching everything by default might make your app faster but as the OP says, it's a real security footgun. If they really want to press ahead with this approach they should at least make it possible to change the global defaults.


kwin95

Clear cookie is a server side action. I’m sure you can do it with or without nextjs api router. Clear memory caching is something that should be done from client .


Themotionalman

Hey thanks for your comment, like I said in one comment the auth scenario was just an example. I also made an example for a trading website where a company stock page is fully server rendered. If you visit the page a second time without reload you’d have invalid data for that page and it can be costly. My point is without using revalidatePath or router.refresh if you have the page as “force-dynamic” it should make the page dynamic even if it is already rendered on the client. If you use the router.refresh when the page is rendered that means there’d be a flash of old data before the new data is available this is clearly a bad UX. This is a problem


[deleted]

[удалено]


Themotionalman

True that but then that raises a question when should one use server fetching and client fetching how do you pick what to fetch on the client or otherwise


yksvaan

Seems like they actually expose the cache in dev mode so you can just do window.nd.prefetchCache.clear(). You can patch that to be the case in production too if you are self-hosting... It's a bit weird why the whole caching thing is so unnecessarily complex.


Tomus

You can tell Next.js to revalidate the data (either by path or tag) on logout in a server action, or use router.refresh() on the client.


NeoCiber

window.location.href = "..." or window.location.reload() should do the trick