Currently, I am in the process of developing a web application using Next.js APP Router for both the frontend and backend components. The frontend takes care of rendering the user interface, while the backend comprises API routes. I require some guidance on how to make fetch requests from the Next.js frontend to the Next.js backend.
The structure of the app directory is as follows:
---/(includes all frontend routes in the pages.ts folder)
---/api(includes all backend routes in the route.js folder)
Included is a Helper function
export const UseFetchFromNext = async (endpoint) =>{
console.log(process.env.NEXT_PUBLIC_VERSION)
const res = await fetch(`${endpoint}`)
const data = await res.json()
console.log(data)
return data;
}
Using this helper function within the server component functions properly.
For instance:
This particular component utilizes
'use client'
useEffect(() => {
fetchData();
console.log(product)
console.log(products)
}, [slug])
const fetchData = async () => {
const productRes = await UseFetchFromNext(`/api/product/${slug}`);
const productsRes = await UseFetchFromNext(`/api/products`);
setProduct(productRes.data);
setProducts(productsRes.data);
}
However, when utilizing the helper function within a server component, it fails to retrieve the default host URL automatically. Therefore, attempting to use fetch separately in the client component like so:
This is a server component example
export default async function Home() {
const res = await fetch(`/api/products`);
const products = await res.json();
}
This method of fetching results in an error because the component is server-side and cannot access the host URL by default.
Internal error: TypeError: Failed to parse URL from /api/products
To resolve this issue, I created a workaround by incorporating a .env file containing:
.env files
NEXT_PUBLIC_API_URL=http://localhost:3000
Then, made fetch requests like this:
Server component (with environment fetch)
export default async function Home() {
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/products`);
const products = await res.json();
}
This approach functions flawlessly during development on my local machine and also successfully builds without errors. However, upon attempting to deploy the application on Vercel, an error is thrown despite having checked all backend routes and optimized them for production.
Vercel error message
TypeError: fetch failed
at Object.fetch (node:internal/deps/undici/undici:11576:11)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
cause: Error: connect ECONNREFUSED 127.0.0.1:3000
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1495:16)
at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) {
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 3000
}
The error can be understood since the environment variable is set to localhost, causing an expected error. How can one obtain the host URL during build time on Vercel deployment when the application is still being processed?
Is there any alternative way to access the environment variable that corresponds to the URL provided by Vercel upon deployment? Any assistance on this matter would be greatly appreciated.