skip to Main Content

I created a demo react app using
npm create vite

I changed the App.tsx as follow :

function App() {

  console.log('!!!!!!!!!!!!!!!!!!')
  console.log(JSON.stringify(import.meta.env))
  console.log('!!!!!!!!!!!!!!!!!!')

  return (
    <h1>MY APP</h1>
  )
}

export default App

I want to pass several environment variables, notably the backend URL.
I have tried to pass it in multiple ways.

my Dockerfile :

FROM nginx:latest AS BASE

# trying setting variable in dockerfile
ENV REACT_APP_BACKEND_URL5=http://www.five.com

# trying to take varibles from environment or args, as I have seen in different posts
ARG REACT_APP_BACKEND_URL1
ARG REACT_APP_BACKEND_URL3
ENV REACT_APP_BACKEND_URL1 $REACT_APP_BACKEND_URL1
ENV REACT_APP_BACKEND_URL3 $REACT_APP_BACKEND_URL3

#delete default welcome page
RUN rm -rf /user/share/nginx/html/*

# copying the built app
COPY ./dist /usr/share/nginx/html

# exposing the port where nginx is listening to the outside
EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

my docker-compose.yml :

version: '3.7'

services:
  myapp:
    container_name: app_front
    build:
      context: .
      args:
        - REACT_APP_BACKEND_URL3=http://www.three.com
        - REACT_APP_BACKEND_URL4=http://www.four.com
    ports:
      - 8080:80
    environment:
      - REACT_APP_BACKEND_URL1=http://www.one.com
      - REACT_APP_BACKEND_URL2=http://www.two.com

how I run the app :

npm run build
docker-compose up

when opening a terminal in the newly created container,

echo $REACT_APP_BACKEND_URL<NUMBER>

returns the expected value for all variables but #4.
so the variables were indeed set in the container.
however, when opening localhost:8080 and looking in the console, I can only see
{"BASE_URL":"/","MODE":"production","DEV":false,"PROD":true,"SSR":false}

what is my problem?
thanks

2

Answers


  1. Vite and other build tools read your environment variables and replace their references in your code with its value. Meaning: The value from build time is already hardcoded into your JavaScript build and can only be changed with a lot of effort. This is because the JavaScript runs in the Browser of your user and the user does not have access to the env vars in your docker container.

    What do you do now?
    You need to get your backend url from somewhere else somehow.
    There are multiple ways to achieve it.
    I don’t know if this can be called a best practice, but here is how I usually achieve a react build that can be configured at runtime:

    1. I create a middleware in my backend that returns a config meant for your frontend when I open a url ending with /config.json. Inside it is a calculated/configured backend-url
    2. Every time I open my react page the browser makes a request to <current_url>/config.json (nginx has to be configured to redirect /config.json to your backend; use a hardcoded url in dev)
    3. Browser (react code) saves the received url and uses it for every future request
    Login or Signup to reply.
  2. The environment variables solution provided by Vite and many other tools is to replace environment variables at build time.

    If you want to use environment variables after build your application, you could:

    1. Import an external env.js file in your index.html.

      <script src='/env.js'></script>
      <script src='/main.js'></script>
      
      function App() {
        console.log('!!!!!!!!!!!!!!!!!!')
        console.log(JSON.stringify(env)
        console.log('!!!!!!!!!!!!!!!!!!')
      
        return (
          <h1>MY APP</h1>
        )
      }
      
      export default App
      
    2. Build your application with Vite.

    3. Generate the env.js just before starting your nginx.

      window.env = {
        'FOO': 'bar'
      }
      
    4. Start the nginx server.

    If this make sense for you, maybe you could give my package: runtime-env a try, this package could save you a lot of time for developing and debugging the solution.

    Plus, here is a complete docker example too: https://github.com/runtime-env/runtime-env/tree/main/examples/production

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search