16

I have a Strapi backend and Next.js frontend app deployed on DigitalOcean. On DigitalOcean is set an environment variable for the frontend: API_URL = ${APP_URL}/api

I fetch this variable to generate the base url:

// constants.js
export const BASE_URL =
  process.env.NODE_ENV === "production"
    ? process.env.API_URL
    : "http://localhost:1337";

It seems to work fine, the app fetch the content from the backend in localhost and in deploy as well. The problem comes when I try to load images which path should be the concatination of the base url and the fetched relative path. I have created a utilitz function for this:

// utilities.js
import { BASE_URL } from "./constants";
export const getImageURL = (relPath) => `${BASE_URL}${relPath}`;

When I use this function for an html img tag it loads both in dev and in prod environments:

<img src={getImageURL(homePage.Hero[0].Image.url)} />

But when I try to set a background for a div in the same component the base url is undefined and the image doesn't appear in the deployed site (works fine on localhost).

I have no idea why the url generation is OK for some part of the code and not OK for the other.

The build command for deploy is: yarn build && next export -o _static

Here is the full component:

import styles from "../styles/Home.module.css";
import { getImageURL } from "../lib/utilities";
import { useEffect } from "react";
import { BASE_URL } from "../lib/constants";

export default function Home({ homePage }) {
  console.log(BASE_URL); // undefined

  useEffect(() => {
    if (window) {
      console.log(BASE_URL); // undefined
      document.getElementById("container").style.backgroundImage = `url('${getImageURL(homePage.Hero[0].Image.url)}')`; // url is undefined/realtivepath
    }
  });


  return (
    <div id="container">
      <img src={getImageURL(homePage.Hero[0].Image.url)} />
    </div>
  );
}

export const getStaticProps = async () => {
  const res = await fetch(`${BASE_URL}/home-page`); // OK for dev and deploy
  const homePage = await res.json();
  return {
    props: {
      homePage,
    },
  };
};

1
  • Can you share your next.config.js file? Commented Apr 24, 2021 at 10:37

2 Answers 2

26

By default, Next.js not exposing all process.env.X variables, due to security concerns, to the browser.

In order to expose environment variable to the browser it must have a prefix of NEXT_PUBLIC_ in the name.

In your case, rename API_URL to NEXT_PUBLIC_API_URL, and use it.

For more info: https://nextjs.org/docs/basic-features/environment-variables

Sign up to request clarification or add additional context in comments.

9 Comments

What if you have multiple services, how to select the correct env? Seems everything loads under 'production'
I'm not sure by "multiple services", next.js is one process, which load .env file
For example, staging, production and dev might be cloud services that all require production builds.
There is, look at this: stackoverflow.com/a/61750672/2522105
If you want NextJS to consume environment variables at runtime, I recommend to use next-runtime-env package: npmjs.com/package/next-runtime-env. This package allowed me to easily reuse the same Docker image across multiple environments, where each env had it's own API_URL set via Docker container environment variable.
|
1

I achieve it like this

const fetchProducts = async () => {
  const response = await fetch(`${process.env.NEXT_PUBLIC_APP_API_ENDPOINT}/products`);
  const data = await response.json();
  setProducts(data.products);
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.