Next.js Discord

Discord Forum

How increase speed of NextJS

Unanswered
California pilchard posted this in #help-forum
Open in Discord
California pilchardOP
I have my app running but she is pretty slow and I dont know why. So I need help for best practice and maybe find the problematic part. I have this example :
https://medusa-b2c-starter-storefront.vercel.app/
Look how its fast for everything, I dont know why I dont have this.
So I just keep a basic page /app/[lang]/page.tsx :
export default function Home() {
    return (
        <div>HOME</div>
    )
}

And /app/[lang]/layout.tsx :
 export default async function Layout({
    children,
  }: RootLayoutProps) {
    return (
      <html suppressHydrationWarning>
        <body>
          {children}
        </body>
      </html>
    );
  }


And my middleware :
const intlMiddleware = createIntlMiddleware(routing);

// make a basic middleware just with intlMiddleware without Supabase auth middleware
export async function middleware(request: NextRequest) {
  return intlMiddleware(request);
}


Its fast but still slower than the example, but damn why I just have a empty page and I use next-intl, is it the problem ?

43 Replies

Miniature Pinscher
Are you running the dev server or a production build?
@Miniature Pinscher Are you running the dev server or a production build?
California pilchardOP
in dev but I know is slower on dev but even running the example one in dev is still way faster than my app
Like route through another page is instant
Miniature Pinscher
Are you using turbopack for both?
California pilchardOP
no turbopack
@California pilchard Like route through another page is instant
Miniature Pinscher
That could be achieved with prefetching.
@Miniature Pinscher That could be achieved with prefetching.
California pilchardOP
But prefechting is done by default with Link no ?
There is an example (first is the example in production) and second my app (in production too). Wayy slower
@Miniature Pinscher Yes, but only fully for static routes.
California pilchardOP
But even the refresh time is way faster in the example, isnt only prefetching right ?
@Miniature Pinscher Are you caching your fetches?
California pilchardOP
the most queries are done client side with react-query soo
Miniature Pinscher
Well, as I said. Add prefetch to all your Links if you want the site to be as snappy as possible.
@California pilchard the most queries are done client side with `react-query` soo
Miniature Pinscher
That's one major difference between your site and the other one then.
California pilchardOP
for example my movie page I do this, my layout.tsx :
export async function generateMetadata({
    params,
}: {
    params: {
      lang: string;
      film: string;
    };
}) {
    const { movie } = await getMovie(params.film, params.lang);
    if (!movie) return { title: 'Film introuvable' };
    return {
        title: movie.title,
        description: `This is the page of ${movie.title}`,
    };
}

export default async function MovieLayout({
    children,
    params,
}: {
    children: React.ReactNode;
    params: {
      lang: string;
      film: string;
    };
}) {
    const { id, movie } = await getMovie(params.film, params.lang);
    if (!movie) notFound();
    return (
        <>
            <MovieHeader movie={movie as any} />
            <div className="px-4 pb-4">
                <MovieNavbar movieId={id} />
                {children}
            </div>
        </>
    );
};

And page.tsx also have the getMovie() function :
export default async function MoviePage({
  params,
}: {
  params: {
    lang: string;
    film: string;
  };
}) {
    const { movie } = await getMovie(params.film, params.lang);
    if (!movie) notFound();
    return <MovieDescription movie={movie as any} />;
}

My query getMovie is supposed to be share with all 3 calls right ? Liike having only one call ?
export const getMovie = cache(async (id: string, lang: string) => {
    /// my function
})
Miniature Pinscher
Yes.
@Miniature Pinscher That's one major difference between your site and the other one then.
California pilchardOP
Mine should be faster for rendering first element so ? If I have some Skeleton for loading state
Miniature Pinscher
Deduped.
Depends on if you leverage streaming.
California pilchardOP
Of my leverage streaming ? What do u means by that ?
Also I use cache() but I dont really understand the difference with unstable_cache (but when using unstable_cache I have an error because my supabase client use cookies()
@Miniature Pinscher You can move out the cookie accessing outside of the `unstable_cache`.
Miniature Pinscher
As an example:

export async function getSomeQuery() {
  const cookies = await cookies()
  const client = someClient(cookies)

  return unstable_cache(
    async () =>
      client.someQuery()
    [],
    {
      tags: [`query:${client.userId}`],
      revalidate: 60 * 60 * 24,
    },
  )();
}
Miniature Pinscher
As opposed to unstable_cache, cache() is only for memoization of non-fetch functions, meaning it will only dedupe the request across the same render, not cache the data for subsequent requests.
@Miniature Pinscher As an example: js export async function getSomeQuery() { const cookies = await cookies() const client = someClient(cookies) return unstable_cache( async () => client.someQuery() [], { tags: [`query:${client.userId}`], revalidate: 60 * 60 * 24, }, )(); }
California pilchardOP
But do with unstable_cache the query is made once if the function is call from multiple element (page, generateMetadata, layout) ? Because doing this :
export const getMovie = (id: string, lang: string) => {
    const supabase = createServerClient();
    return unstable_cache(async () => {
        //getting data with supabase
        console.log('REQUEST MOVIE');
        return {
            id: movieId,
            movie,
        };
    }, [lang, 'movie', id], {
        revalidate: 60 * 60 * 24,
    })();
}

I have 3 console.logs, while with cache only one
Miniature Pinscher
Well for one, you put the tags at the wrong place

export const getMovie = (id: string, lang: string) => {
  const supabase = createServerClient();
  return unstable_cache(
    async () => {
      //getting data with supabase
      console.log("REQUEST MOVIE");
      return {
        id: movieId,
        movie,
      };
    },
    [],
    {
      revalidate: 60 * 60 * 24,
      tags: [lang, "movie", id],
    },
  )();
};
California pilchardOP
I have the same results :
    }, [], {
        revalidate: 60 * 60 * 24,
        tags: [lang, 'movie', id],
    })();

Also 3 console.log...
Miniature Pinscher
Make sure the function is marked as async
@Miniature Pinscher Make sure the function is marked as async
California pilchardOP
Which one ? There is the entire function :
export const getMovie = async (id: string, lang: string) => {
    const supabase = createServerClient();
    return unstable_cache(async () => {
        const { id: movieId } = getIdFromSlug(id);
        const { data: movie, error } = await supabase
            .from('movie')
            .select(`
                *,
                cast:tmdb_movie_credits(
                    id,
                    person:person(*),
                    role:tmdb_movie_role(*)
                ),
                production_countries:tmdb_movie_country(
                    id,
                    country:tmdb_country(
                        *,
                        data:tmdb_country_translation(*)
                    )
                ),
                spoken_languages:tmdb_movie_language(
                    id,
                    language:tmdb_language(
                        *,
                        data:tmdb_language_translation(*)
                    )
                ),
                videos:tmdb_movie_videos(*)
            `)
            .match({
                'id': movieId,
                'cast.job': 'Actor',
                'production_countries.country.data.language': lang,
                'spoken_languages.language.data.language': lang,
                'videos.iso_639_1': lang
            })
            .maybeSingle();
        if (error) throw error;
        console.log('REQUEST MOVIE');
        return {
            id: movieId,
            movie,
        };
    }, [], {
        revalidate: 60 * 60 * 24,
        tags: [lang, 'movie', id],
    })();
}
And the page where she is called :
export async function generateMetadata({
    params,
}: {
    params: {
      lang: string;
      film: string;
    };
}) {
    const { movie } = await getMovie(params.film, params.lang);
    if (!movie) return { title: 'Film introuvable' };
    return {
        title: movie.title,
        description: `This is the page of ${movie.title}`,
    };
}

export default async function MovieLayout({
    children,
    params,
}: {
    children: React.ReactNode;
    params: {
      lang: string;
      film: string;
    };
}) {
    const { id, movie } = await getMovie(params.film, params.lang);
    if (!movie) notFound();
    return (
        <>
            <MovieHeader movie={movie as any} />
            <div className="px-4 pb-4">
                <MovieNavbar movieId={id} />
                {children}
            </div>
        </>
    );
};
Miniature Pinscher
That looks correct at first glance. Are you sure you're importing the right getMovie function?
@Miniature Pinscher That looks correct at first glance. Are you sure you're importing the right `getMovie` function?
California pilchardOP
sadly yes I only have one getMovie function in my code
even with this test one :
export const test = unstable_cache(async () => {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    console.log('THIS IS A TEST');
    return 'test';
}, [], {
    revalidate: 60 * 60 * 24,
    tags: ['test'],
});
2 consoles logs
Miniature Pinscher
I ran your exact code snippet and I'm only getting one console log.
Which Next version are you on?
@Miniature Pinscher Which Next version are you on?
California pilchardOP
Next 14.2.16
@Miniature Pinscher I ran your exact code snippet and I'm only getting one console log.
California pilchardOP
thats crazy ahah
maybe there is something to enable for caching idk ?
@California pilchard `Next 14.2.16`
Miniature Pinscher
I might be wrong, but unstable_cache is only supported on > 15.0
@Miniature Pinscher I might be wrong, but `unstable_cache` is only supported on > 15.0
California pilchardOP
ohhh well I can try upgrade
@Miniature Pinscher I might be wrong, but `unstable_cache` is only supported on > 15.0
California pilchardOP
just updated to nextjs 15, same problem
@Miniature Pinscher I might be wrong, but `unstable_cache` is only supported on > 15.0
California pilchardOP
simple NextJS 15 page with that :
export async function generateMetadata(
    props: { params: Promise<{ lang: string; film: string; }> }
) {
    const dataTest = await test();
}

export default async function PageTest(
    props: {
        children: React.ReactNode;
        params: Promise<{
          lang: string;
          film: string;
        }>;
    }
) {
    const dataTest = await test();
    return (
        <div className='text-black'>
            test sef sef
        </div>
    )
};

I have no idea how u success make the test function console log once