Nextjs Link slow to fetch page and dynamic page when i deploy on aws amplify
Unanswered
Saltwater Crocodile posted this in #help-forum
Saltwater CrocodileOP
0
I am using Next.js 14.2.3 to build a website, the other pages on the website are static generated at build time and static rendered, on the other hand, i have a page or route that is dynamically rendered. On local dev, when i click on the link go to the page, "http://localhost:3000/test", it renders quickly but when this is deployed on aws amplify, and i go to the page "https://test.d2oa4hihp69p02.amplifyapp.com/test/" the page takes about 10 seconds to open and sometimes i get the error. "This page isn’t working test.d2oa4hihp69p02.amplifyapp.com took too long to respond. HTTP ERROR 504". I also have similar problems when i click on a link to view a single dynamic page within the test page https://test.d2oa4hihp69p02.amplifyapp.com/test/webstreams-medical-training-goes-global
I read and followed this part of nextjs documentation https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes. am i doing it wrongly? because it works perfectly in my local dev.
I am using Next.js 14.2.3 to build a website, the other pages on the website are static generated at build time and static rendered, on the other hand, i have a page or route that is dynamically rendered. On local dev, when i click on the link go to the page, "http://localhost:3000/test", it renders quickly but when this is deployed on aws amplify, and i go to the page "https://test.d2oa4hihp69p02.amplifyapp.com/test/" the page takes about 10 seconds to open and sometimes i get the error. "This page isn’t working test.d2oa4hihp69p02.amplifyapp.com took too long to respond. HTTP ERROR 504". I also have similar problems when i click on a link to view a single dynamic page within the test page https://test.d2oa4hihp69p02.amplifyapp.com/test/webstreams-medical-training-goes-global
I read and followed this part of nextjs documentation https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes. am i doing it wrongly? because it works perfectly in my local dev.
10 Replies
Saltwater CrocodileOP
Here is my server component code below,
async function Test({ searchParams, params: { lang } }) {
const query = searchParams?.query "";
const sort = searchParams?.sort "ASC";
const industry = searchParams?.industry || "";
let casestudies = await getAllCStudies(
industry,
BATCH_SIZE,
null,
null,
null,
sort,
"DATE",
query,
lang
);
let categories = await getCaseStudyCategories("en");
return (
<div>
{casestudies.nodes.map((item) => {
return (
<div style={{ fontSize: "2rem", padding: "1rem", cursor: "pointer" }}>
<Link href={
{item.title} <br />
</Link>
</div>
);
})}
</div>
);
}
export default Test;
async function Test({ searchParams, params: { lang } }) {
const query = searchParams?.query "";
const sort = searchParams?.sort "ASC";
const industry = searchParams?.industry || "";
let casestudies = await getAllCStudies(
industry,
BATCH_SIZE,
null,
null,
null,
sort,
"DATE",
query,
lang
);
let categories = await getCaseStudyCategories("en");
return (
<div>
{casestudies.nodes.map((item) => {
return (
<div style={{ fontSize: "2rem", padding: "1rem", cursor: "pointer" }}>
<Link href={
/test/${item.slug}}>{item.title} <br />
</Link>
</div>
);
})}
</div>
);
}
export default Test;
Here are the functions that calls the endpoint
export async function getAllCStudies(
categoryName,
first,
after,
last,
before,
order,
field,
query,
lang
) {
const orderby = {
order,
field,
};
const variables = {
orderby: [{ field, order }],
first,
after,
last,
before,
query,
lang,
};
let categoryFilter = "";
if (categoryName) {
variables.categoryName = categoryName;
categoryFilter = "$categoryName: String!,";
}
const data = await fetchAPI(
{
variables,
}
);
return data?.casestudies;
}
export async function getAllCStudies(
categoryName,
first,
after,
last,
before,
order,
field,
query,
lang
) {
const orderby = {
order,
field,
};
const variables = {
orderby: [{ field, order }],
first,
after,
last,
before,
query,
lang,
};
let categoryFilter = "";
if (categoryName) {
variables.categoryName = categoryName;
categoryFilter = "$categoryName: String!,";
}
const data = await fetchAPI(
query Casestudy ($orderby: [PostObjectsConnectionOrderbyInput], $first: Int, $after: String, $last: Int,$before: String, $query: String, $lang: String, ${categoryFilter}) {
casestudies(where: { ${
categoryName ? "categoryName: $categoryName," : ""
} orderby: $orderby, search: $query, language: $lang }, first: $first, after: $after, last: $last, before: $before) {
nodes {
title
slug
date
casestudies {
metatitle
metadescription
description
companyLogo {
mediaItemUrl
srcSet
altText
}
companyName
mainimage {
altText
mediaItemUrl
}
}
categories {
nodes {
id
name
}
}
}
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
}
},{
variables,
}
);
return data?.casestudies;
}
export async function fetchAPI(query = "", { variables } = {}) {
const res = await fetch("https://apibkofc.globalvoices.com/graphql", {
next: { revalidate: 30 },
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables,
}),
});
if (!res.ok) {
console.error(res);
return {};
}
const { data } = await res.json();
return data;
}
const res = await fetch("https://apibkofc.globalvoices.com/graphql", {
next: { revalidate: 30 },
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables,
}),
});
if (!res.ok) {
console.error(res);
return {};
}
const { data } = await res.json();
return data;
}
first things in the page component, you are doing two fetch in sequence:
you can move to something in parallel using
with await:
async function Test({ searchParams, params: { lang } }) {
const query = searchParams?.query "";
const sort = searchParams?.sort "ASC";
const industry = searchParams?.industry || "";
let casestudies = await getAllCStudies(
industry,
BATCH_SIZE,
null,
null,
null,
sort,
"DATE",
query,
lang
);
let categories = await getCaseStudyCategories("en");
return (
<div>
{casestudies.nodes.map((item) => {
return (
<div style={{ fontSize: "2rem", padding: "1rem", cursor: "pointer" }}>
<Link href={/test/${item.slug}}>
{item.title} <br />
</Link>
</div>
);
})}
</div>
);
}you can move to something in parallel using
Promise.all, see the documentation here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allwith await:
let [a, b, c] = await Promise.all([promiseA, promiseB, promiseC]);On the other part, if you are using app router, you can take use
I've used https://buildui.com/recipes/await-component successfully to make streaming easy
<Suspense> to your advantage to return the layout of the page and stream automatically the rest.I've used https://buildui.com/recipes/await-component successfully to make streaming easy
Saltwater CrocodileOP
<Suspense fallback={<p>Loading casestudies...</p>}>
{casestudies.nodes.map((item) => {
return (
<div
style={{ fontSize: "2rem", padding: "1rem", cursor: "pointer" }}
>
<Link href={
{item.title} <br />
</Link>
</div>
);
})}
</Suspense>
async function SingleCaseStudy({ params }) {
const { slug } = params;
let caseStudyData = await fetchCStudyBySlug(slug);
console.log(caseStudyData, "SINGLE SLUG");
return (
<div>
<h1>Single case study</h1>
<Suspense fallback={"loading casestudy..."}>
{caseStudyData.casestudy.title}
</Suspense>
</div>
);
}
export default SingleCaseStudy;
I added suspense to the page and also to the single dynamic page, i still have the same problem, please does this have to do with aws amplify, or is there another way around this?
{casestudies.nodes.map((item) => {
return (
<div
style={{ fontSize: "2rem", padding: "1rem", cursor: "pointer" }}
>
<Link href={
/test/${item.slug}}>{item.title} <br />
</Link>
</div>
);
})}
</Suspense>
async function SingleCaseStudy({ params }) {
const { slug } = params;
let caseStudyData = await fetchCStudyBySlug(slug);
console.log(caseStudyData, "SINGLE SLUG");
return (
<div>
<h1>Single case study</h1>
<Suspense fallback={"loading casestudy..."}>
{caseStudyData.casestudy.title}
</Suspense>
</div>
);
}
export default SingleCaseStudy;
I added suspense to the page and also to the single dynamic page, i still have the same problem, please does this have to do with aws amplify, or is there another way around this?
The component under the suspense need to await
// src/app/stocks/[stockId]/page.tsx
import { Await } from "@/components/await";
export default async function Stock({
params,
}: {
params: { stockId: string };
}) {
// Page blocks on this data:
const stock = await getStock(params.stockId);
return (
<div>
<h1>{stock.name}</h1>
<Suspense fallback={<Spinner />}>
{/* ...but renders a spinner for this slower data: */}
<Await promise={getRecentNews(stock)}>
{(stories) => (
<ul>
{stories.map((story) => (
<li key={story.id}>{story.title}</li>
))}
</ul>
)}
</Await>
</Suspense>
</div>
);
}Saltwater CrocodileOP
Thank you very much, this solution helped