Next.js Discord

Discord Forum

how to dedup a function call used in params, metadata, and page function

Answered
Yellow-horned horntail posted this in #help-forum
Open in Discord
Yellow-horned horntailOP
i am using an function call which uses filesystem 'fs' module and scraps all relative objects. lets call it getAllBlogPosts. now in my page route, i am using this function in generateStaticParams, generateMetadata, and also in the Page functino body, so there are total of 3 function calls.
if this were a fetch call, i would be assured that the result is cached and i would not worry about using it, but since i am using 'fs', i wonder if it is being cached, and if its not, is there any way i can dedup the function calls?
export async function generateStaticParams() {
    let posts = getBlogPosts();

    return posts.map((post) => ({
        slug: post.slug,
    }));
}

export function generateMetadata({ params }) {
    let post = getBlogPosts().find((post) => post.slug === params.slug);
    if (!post) return;
    let {
        title,
        publishedAt: publishedTime,
        summary: description,
        image,
    } = post.metadata;
    let ogImage = image
        ? image
        : `${baseUrl}/og?title=${encodeURIComponent(title)}`;

    return {
        title,
        description,
        openGraph: {
            title,
            description,
            type: "article",
            publishedTime,
            url: `${baseUrl}/blog/${post.slug}`,
            images: [
                {
                    url: ogImage,
                },
            ],
        },
        twitter: {
            card: "summary_large_image",
            title,
            description,
            images: [ogImage],
        },
    };
}

export default function Blog({ params }) {
    let post = getBlogPosts().find((post) => post.slug === params.slug);
    if (!post) {
        notFound();
    }
    const toc = parseToc(post.content);
return(<div></div>)

how can i dedup function call here(if its not cached?) is it okay to actually call the function three times here?
Answered by joulev
Use React.cache to dedupe the function call
View full answer

12 Replies

Yellow-horned horntailOP
from my understandings, the call in generateStaticParams is going to be only called in build time and no more in run time, so excluding that, the remaining two function calls are called on runtime. if its correct, is it okay to call the same functoin twice here?
@Yellow-horned horntail i am using an function call which uses filesystem 'fs' module and scraps all relative objects. lets call it getAllBlogPosts. now in my page route, i am using this function in generateStaticParams, generateMetadata, and also in the Page functino body, so there are total of 3 function calls. if this were a fetch call, i would be assured that the result is cached and i would not worry about using it, but since i am using 'fs', i wonder if it is being cached, and if its not, is there any way i can dedup the function calls? export async function generateStaticParams() { let posts = getBlogPosts(); return posts.map((post) => ({ slug: post.slug, })); } export function generateMetadata({ params }) { let post = getBlogPosts().find((post) => post.slug === params.slug); if (!post) return; let { title, publishedAt: publishedTime, summary: description, image, } = post.metadata; let ogImage = image ? image : `${baseUrl}/og?title=${encodeURIComponent(title)}`; return { title, description, openGraph: { title, description, type: "article", publishedTime, url: `${baseUrl}/blog/${post.slug}`, images: [ { url: ogImage, }, ], }, twitter: { card: "summary_large_image", title, description, images: [ogImage], }, }; } export default function Blog({ params }) { let post = getBlogPosts().find((post) => post.slug === params.slug); if (!post) { notFound(); } const toc = parseToc(post.content); return(<div></div>) how can i dedup function call here(if its not cached?) is it okay to actually call the function three times here?
Use React.cache to dedupe the function call
Answer
@joulev Use React.cache to dedupe the function call
Yellow-horned horntailOP
i haven thought about that. thanks.so 'fs' calls are not cached, right?
another question is, if i use 'cache' is it ok to declare the cache function outside of the nextjs function, say globally?
like this:
const postCache = cache(getBlogPosts);
export async function generateStaticParams() {
    let posts = postCache();

    return posts.map((post) => ({
        slug: post.slug,
    }));
}

export function generateMetadata({ params }) {
    let post = postCache().find((post) => post.slug === params.slug);
    if (!post) return;
    let {
        title,
        publishedAt: publishedTime,
        summary: description,
        image,
    } = post.metadata;
    let ogImage = image
        ? image
        : `${baseUrl}/og?title=${encodeURIComponent(title)}`;

    return {
        title,
        description,
        openGraph: {
            title,
            description,
            type: "article",
            publishedTime,
            url: `${baseUrl}/blog/${post.slug}`,
            images: [
                {
                    url: ogImage,
                },
            ],
        },
        twitter: {
            card: "summary_large_image",
            title,
            description,
            images: [ogImage],
        },
    };
}
if so, if i am in a different file of the same route, say 'layout.tsx' or 'template.tsx', can i import the cached function?
American Crow
I think you are trying to achieve a similar thing i did couple of weeks ago.
I am guessing it's about mdx files read from disk and statically generated?

Pretty sure generateMetadatais also only called on build when combined with generateStaticParams. So the 2 functions you are trying to cache reduce to one (which doesnt make sense ofc.).

When i remember correctly i ended up successfully caching the data read from the fs however when my mdx files exceeded 1.000 files i quickly ran out of memory, which makes sense. So that stuff being on disk and not in memory actually makes some sense.
Sorry for not awnsering your question directly
(I ended up not caching anything)
American Crow
The rules fo React.cache are the following:
- React will invalidate the cache for all memoized functions for each server request.
- Each call to cache creates a new function. This means that calling cache with the same function multiple times will return different memoized functions that do not share the same cache.
- cache is for use in Server Components only.

Globally is okay. But it has to be the same request
@joulev but yeah, cache takes resources so if you cache too many things, it will break one way or another
American Crow
yea you are right i was kind of limit testing and realized i am optimizing a system which was not designed for that. Just shared it in case OP is going down the same rabbit hole
Yellow-horned horntailOP
that surely helped a lot. thanks legends!