How increase speed of NextJS
Unanswered
Pacific herring posted this in #help-forum
Pacific herringOP
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
And
And my middleware :
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 ?
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?
Pacific herringOP
in
dev but I know is slower on dev but even running the example one in dev is still way faster than my appLike route through another page is instant
Miniature Pinscher
Are you using turbopack for both?
Pacific herringOP
no turbopack
@Pacific herring Like route through another page is instant
Miniature Pinscher
That could be achieved with prefetching.
@Miniature Pinscher That could be achieved with prefetching.
Pacific herringOP
But prefechting is done by default with
There is an example (first is the example in production) and second my app (in production too). Wayy slower
Link no ?There is an example (first is the example in production) and second my app (in production too). Wayy slower
@Pacific herring 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.
@Miniature Pinscher Yes, but only fully for static routes.
Pacific herringOP
But even the refresh time is way faster in the example, isnt only prefetching right ?
@Pacific herring But even the refresh time is way faster in the example, isnt only prefetching right ?
Miniature Pinscher
Are you caching your fetches?
@Miniature Pinscher Are you caching your fetches?
Pacific herringOP
the most queries are done client side with
react-query sooMiniature Pinscher
Well, as I said. Add prefetch to all your Links if you want the site to be as snappy as possible.
@Pacific herring 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.
Pacific herringOP
for example my movie page I do this, my
And
My query
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.
Pacific herringOP
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.
Pacific herringOP
Of my
Also I use
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()@Pacific herring 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 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,
},
)();
}
Pacific herringOP
But do with
I have 3 console.logs, while 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 oneMiniature 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],
},
)();
};Pacific herringOP
I have the same results :
Also 3 console.log...
}, [], {
revalidate: 60 * 60 * 24,
tags: [lang, 'movie', id],
})();Also 3 console.log...
@Miniature Pinscher Well for one, you put the tags at the wrong place
js
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],
},
)();
};
Pacific herringOP
Even with static tag like ['movie']
Miniature Pinscher
Make sure the function is marked as async
@Miniature Pinscher Make sure the function is marked as async
Pacific herringOP
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?
Pacific herringOP
sadly yes I only have one
getMovie function in my codeeven 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?
Pacific herringOP
Next 14.2.16@Miniature Pinscher I ran your exact code snippet and I'm only getting one console log.
Pacific herringOP
thats crazy ahah
maybe there is something to enable for caching idk ?
@Pacific herring `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
Pacific herringOP
ohhh well I can try upgrade
@Miniature Pinscher I might be wrong, but `unstable_cache` is only supported on > 15.0
Pacific herringOP
just updated to nextjs 15, same problem
@Miniature Pinscher I might be wrong, but `unstable_cache` is only supported on > 15.0
Pacific herringOP
simple NextJS 15 page with that :
I have no idea how u success make the test function console log once
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