#yes that cache does not invalidate nor

1 messages · Page 1 of 1 (latest)

faint crane
#

In that case, why Next Documentation is mentioning the revalidation?

#

or did I get it wrong?

storm zealot
#

different cache

#

that example uses 2 separate cache

#

cache() to dedupe function

#

and revalidate = 3600 will cache the build result of layout/page (called the full router cache in this case)

faint crane
#

what's the purpose of the react cache in this scenario than?

storm zealot
#

to dedupe the calls

#

getItem might be called multiple times in separate server components

#

its job is to dedupe it and made sure its only get called once

faint crane
#

So this will be cached like forever and will not update, correct?

storm zealot
#

which "this"

#

there are 2 types caches being used

faint crane
#

getItem with react cache

storm zealot
#

no it wont be cached forever

#

it only dedupe calls in a single request

#

so if I request to server for /dashboard
and dashboard has 3 server components <A/> <B/> <C/> each calls getItem it will only call getItem once and not thrice

#

if I call /dashboard again, then it will call getItem once again.

#

if I request /dashboard again, then it will call getItem once again

#

assuming the /dashboard route is not cached

edgy trout
#

this 'works' for me but absoltuely not the cleanest and im sure it can be improved. just wanted to show a working example

import prisma from '@/db/prisma';
import { unstable_cache } from 'next/cache';

//Types go here

const getCachedExercises = unstable_cache(
    async () => {
        //Check to see when the db is actually being queried
        console.log("Fetching exercises from the database");
        return await prisma.exercise.findMany();
    },
    ['exerciseList'],
    {
        tags: ['exercises'], //revalidate on demand if needed
        revalidate: 30000, // revalidate after 30 seconds otherwise
    }
);

export default async function getExercises(): Promise<Exercise[]> {
    return await getCachedExercises();
}

storm zealot
#

this however, unstable_cache, will cache the result for the next request

#

so it persists data in between requests

#

but there are many ways to persists data in between request

#

depending how you want to cache stuff

faint crane
#

I was looking at unstable_cache today and thinking about to give it a try. Do you think it's suitable for production of simple one page website?

storm zealot
#

to be honest i can't tell unless you tell me what do you want to cache and what for

#

coz i dont know the use case

faint crane
#

The scenario I want to achieve is that I want to cache prisma results and revalidate it once a day. I know my data does not change very often and if it changes it does not has to be reflected immedieately on the frontend

storm zealot
#

just prisma cache results? what prisma cache result? how many component will use the prisma result? is it just being used in a single component or will it be reusable in other component or places?

edgy trout
#

for me when im using unstable_cache the main issue is dealing with cached user data. i've been trying out so many things but ultimately i had to remove all caching on user data becuase it gets impractical with large user base. unstable_cache is perfect for caching prisma fetches that arent user specific imo

storm zealot
#

whats the problem with cached user data?

faint crane
#

@edgy trout so for caching non user specific data is it ok?

edgy trout
# storm zealot whats the problem with cached user data?

we actually spoke about it a while back. In a situation where you are doing a prisma find 'where: userId' that needs to be revalidated by a tag that includes the userId you'd end up with tonnes of individual caches, say you have a bunch of Models and thousands of users.

storm zealot
#

ah so its like a size issue

#

aha

edgy trout
#

i dont know where the cache is stored or how its maintained but i had to remove it from a prod app because it was having memory issues, it did work but im not sure how to manage all that cache. i think we said using redis was a better solution

storm zealot
#

i think its stored in the memory

#

i have a slight suspicion that its stored in the memory

#

because the memory gets persisted in Serverless Function

#

both in dev and prod

edgy trout
#

while doing research i saw people saying their unstable_cache was getting mixed up and returning the wrong data but that seems to be user specific caches

faint crane
# storm zealot just prisma cache results? what prisma cache result? how many component will use...

https://3int.uk/ This is my website. It's served on Digital Ocean App Platform. It's my first app created using next and starting point for more complex projects I am planning to do. So every section is a dynamic component and it is being generated from a mongo collection. However the structure will rarely change so it should be cached. Also navbar component is making same call for that collection as it composes dynamically hash links. Than every content in sections is being stored in collections as well so again I'd like these to be cached and revalidate them like once a day

edgy trout
edgy trout
storm zealot
faint crane
#

@edgy trout am not sure if am following, but is it possible, that what you are talking about might be actually an issue I am experiencing - when my app is up for 3 days it goes out of memory and actually navbar an dymanic section components returns an error when I click on any menu link

faint crane
storm zealot
edgy trout
#

correct me if im wrong but since you dont have user accounts, couldnt you statically generate the whole site?

storm zealot
#

^

#

what i meant by caching the page

edgy trout
#

and use a webhook to revalidate the cache when you make changes so you dont have to rebuild

faint crane
edgy trout
#

can you run npm run build and show us your build output?

faint crane
#

just sec

edgy trout
#

i would assume it would be statically build by default, but it sounds like ssr

faint crane
#

When I start this project I was trying to do statically generated site, but at some point I failed and I don't remember now why. I am using app router and am not sure if it was related to it.

edgy trout
#

hmm... we can see your main page is statically generated which is very confusing if you're having memory issues.

faint crane
edgy trout
#

/legal/[slug] should be ssg imo not ssr

#

and what is that client async error about? cant you do the fetch in a server component and pass it to the client component?

faint crane
#

I'll update the legal, that's the latest thing I was doing. However it also works preperly when app's out of memory.

edgy trout
#

it does look like a memory leak based on your graph

faint crane
#

the hero is my bad it's async but also client

edgy trout
faint crane
edgy trout
#

you shouldnt need any prisma cache

#

since the only time it will query your db is when you run build

#

after that its justa fully rendered static page

faint crane
#

Ok, I'll revert all the cache. However before using cache any time I did a change in my collection it was reflected on frontend which technically should be if statically generated, correct?

edgy trout
#

i assumed so, maybe @storm zealot can shed some more light on the situation

#

if you make the legal route ssg then i cant imagine any reason you would get memory leaks

#

it could be static too but with ssg you have the option to revalidate it without rebuilding which is nice if you plan to add more posts

faint crane
#

yes this is actually what I want. However am experiecning memory leak since my first deployement with no prisma caching. I read somewhere thet next will consume all dedicated memory over time and it does not do cleanup, but also it should not affect the application.

edgy trout
#

for example in my portfolio site:

Route (app)
┌ ○ /
├ ○ /_not-found 0 B 0 B
├ λ /api/disable-draft 0 B 0 B
├ λ /api/draft 0 B 0 B
├ λ /api/revalidate 0 B 0 B
├ ○ /apple-icon.png 0 B 0 B
├ ○ /projects
├ ● /projects/[slug]
├ ├ /projects/redacted
├ ├ /projects/redacted
├ ├ /projects/redacted
├ └ [+6 more paths]
├ ○ /tech-stack
├ ● /tech-stack/[slug]
├ ├ /tech-stack/redacted
├ ├ /tech-stack/redacted
├ ├ /tech-stack/redacted
├ └ [+11 more paths]
└ ○ /terms

everything is static or ssg but i have some api routes to handle revalidating and other things

#

so when i make a new post a webhook revalidates the cache for me immediately

faint crane
#

could you share that revalidation api? or at least some external resource which is explaning this part ?

#

cause that's actually what I'd like to implement

edgy trout
#

sure thing:

import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'

export async function POST(request: NextRequest) {
  const requestHeaders = new Headers(request.headers)
  const secret = requestHeaders.get('x-vercel-reval-key')

  if (secret !== process.env.CONTENTFUL_REVALIDATE_SECRET) {
    return NextResponse.json({ message: 'Invalid secret' }, { status: 401 })
  }

  revalidateTag('posts')

  return NextResponse.json({ revalidated: true, now: Date.now() })
}

it has some stuff specific to the contentful cms and making it secure but otherwise pretty straightforward

#

this is pretty common for next and headless cms

#

you could for example get github to fire the webhook when you push to your main branch

#

in my example the cms fires the webhook whenever i add or change a post

#

the one drawback being if i make a new post i will have to rebuild or it will be served up dynamically

#

essentially its just an api route that will call revalidateTag, you could use revalidatePath too but i wanted it to be more granular

faint crane
#

Great you just answered what I was planning to ask about. So revalidatePath on root will just revalidate everything, right?

You are using revalidateTag, can look up at documentation, but since you are here, where and how have you specified this tag in your code?

storm zealot
edgy trout
edgy trout
#

But essentially all that will happen is will retrigger all of your server component fetches

#

So tag might be a more efficient approach

#

Regarding your memory leak I have absolutely no idea why that is happening

#

But if you remove SSR from the equation it will make it a lot easier to debug imo

faint crane
edgy trout
faint crane
edgy trout
#

Feel free to dm me if you get stuck. Or make a help post and tag me

#

I’m a noob but working with nextjs all day every day trying to understand the intricacies

faint crane
edgy trout
#

Once you get these minor issues out the way it will be perfect

faint crane
#

thanks it's quite funny you are saying so as Design is my biggest nightmare and I hate it so much. I'd love to write frontend, backend but god please no design.

edgy trout
faint crane
#

yeah, same here. But still it's total drawback when you are trying to write a functionality and than stuck on frontend cause you don't like the look. Definetely worst thing for people with ADHD 😄

edgy trout
faint crane
#

😄 damn, I'm so happy to see there's more people out there having same silly problems :D. Thanks again

faint crane
#

Hey guys, I am gonna continue in this thread as it is easier to follow up.

I was playing a bit with my code and I find out, that caching works actually fine with or without react/cache applied, BUT for some reason it does not work for components in layout.

In my root level layout I've applied 'force-static' and revalidation to 60 seconds (my previous problem was I was using math not exact number, which according to documentation is not supported). Suddenly everything works fine, all my pages are statically generated and revalidates every 60s or on-demand using @edgy trout's API example. However in that layout I have components Navbar and Footer which do access DB as well (to dynamically compose links) and data for these components seems not to be cached. Everytime I hit hard refresh I can see a call to DB for each component. If I comment these components out, these extra calls disappears.

Any idea, why is this happening? I've attached a screenshot - Yellow line is hard refresh, Red line is hard refresh after revalidation call

edgy trout
faint crane
#

Yeah that's definetely a way to avoid this issue. However I'd like to know also a dynamic solution, as this is a starting point for my next project. I've used this simple website only to learn how Next works

edgy trout
#

thats fair, i'll have a think about it and get back to you this evening after work. Maybe its my lack of understanding but i would assume if "/" is being built/rendered as 'static' then there should be no fetching done in the file? since all of the fetching and building happens as build time

faint crane
#

Interestingly If I move the Navbar from the root Layout to root page, it stops re-rendering on hard refresh.

faint crane
#

Hi @edgy trout . I've seen in the chat last week you've been asking about sharp library and as we have discussed memory leak in my prod environment as well I just decided to let you briefly know, that I've solved my memory leak today and it was related to the sharp. Apparently it does not work happely in standard linux distributions. There are some tips in Sharps documentation how to fix that, but for me the easiest way was to deploy my app to container running Alpine linux instead of DO App Platform's Ubuntu. So just in case you'd experience something similar this might be the core issue.