0

I have a really serious question I didn't find the answer about Vercel (NextJS).

I am trying to deploy the project on Versel and I am using some structures to get data from API, example:

export async function getStaticProps(context) {
  const route = process.env.APIpath + 'api/category/getCategories'; //focusing here, ok on localhost
  const res = await fetch(route)
  const json = await res.json()
  return {
    props: {
      data: json,
      },
  };
}

As fetch is using only absolute URL path, I need to define base url with variable process.env.APIpath.

With local testing I have process.env.APIpath = 'http://localhost:3000/' but: I need to define a production variable for Vercel deployment and I am using serverless functions.

Some info about Vercel, according to this documentation, we can actually fetch the data. But during the deployment process, I always have errors on the pages where I am calling fetch, for example:

//this code triggers an error as code shown above, ok on localhost
const res = await fetch(process.env.APIpath + 'api/category/getCategory?_id='+ pid, {
    method: 'post',
    body: JSON.stringify(values, null, 2)
})

I am getting errors because of fetch. Of course, I understand that during the deployment Vercel can't build the production version as I am using "hardcoded" process.env.APIpath.

How can I define clearly the process.env.APIpath (or any different built variables) to deploy the project? Please, note that every time Versel generates generic project link as nextjs-fhp5exsvo-testing.vercel.app.

P.S. Will be happy for any help, having an issue with deployment for about 5 days already.

ChilTest
  • 461
  • 5
  • 18
  • Is this a CRA or Next.js app? – paulogdm Jun 08 '21 at 15:39
  • Next js app. ( will add some info to post now) – ChilTest Jun 08 '21 at 15:39
  • 1
    You should not make calls to internal API routes in `getStaticProps`. Instead, directly import the logic used inside your API route: [Internal API fetch with getServerSideProps? (Next.js)](https://stackoverflow.com/questions/65752932/internal-api-fetch-with-getserversideprops-next-js/65760948#65760948) (mentions `getServerSideProps` but same applies to `getStaticProps`). – juliomalves Jun 08 '21 at 17:55
  • Thanks, but you comment is inscruding fetch I can't really use. – ChilTest Jun 09 '21 at 08:26

2 Answers2

0

How I partially solved my issue

Instead of using getStaticProps and getServerSideProps to fetch data from API, I am using useSWR library. This solution seems to be good with local and production versions.

1.Change to useSWR instead of getStaticProps

not working code with getStaticProps

export async function getStaticProps(context) {
  const route = process.env.APIpath + 'api/category/getCategories'; 
  const res = await fetch(route)
  const json = await res.json()
  return {
    props: {
      data: json,
      },
  };
}

changed to useSWR, working example for local, test, and production

import useSWR from 'swr'
import React from 'react';

//important to return only result, not Promise
const fetcher = (url) => fetch(url).then((res) => res.json());

const Categories = () => {
 //getting data and error
 const { data, error } = useSWR('/api/category/getCategories', fetcher)
 if (error) return <div>Failed to load</div>
 if (!data) return <div>Loading...</div>
 if (data){
   // {data} is completed, it's ok!
   //your code here to make something with {data}
   return (
      <div>
      //something here, example {data.name}
      </div>
   )
 }
}

export default Categories

Notice: I am not sure that useSWR will work perfectly with SEO, but according to this link, we can even use it with SSR.

2.Modifying MongoDB settings.

As I am using mongoDB, you need to check MongoDB settings properly. Once u did it, you need to check your API routes (not pages) are in /pages/api/[apiname].js. Only after API routes work (on Vercel) I suggest you start coding your local version.

3.Change your deployment variables on Vercel.

You need to configure environment variables and some others on Vercel. More details here

ChilTest
  • 461
  • 5
  • 18
0

You can fetch data from an api route using a relative path with Next.js.

Straight from Next.js documentation:

function Profile() {
  const [data, setData] = useState(null)
  const [isLoading, setLoading] = useState(false)

  useEffect(() => {
    setLoading(true)
    fetch('api/profile-data')  // <-- relative path
      .then((res) => res.json())
      .then((data) => {
        setData(data)
        setLoading(false)
      })
  }, [])

  if (isLoading) return <p>Loading...</p>
  if (!profileData) return <p>No profile data</p>

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.bio}</p>
    </div>
  )
}

Next.js docs do also explicitly recommend using SWR, like @ChilTest's answer suggests. That said, the relative path is not a special SWR-only feature.

ptpaterson
  • 9,131
  • 4
  • 26
  • 40