skip to Main Content

at work I need to make it possible to change the environmet variables at runtime, from an Azure web service, through docker and nginx.
I tried this, this and some similar solutions, but I couln’t get any of them to work.

I also couldn’t find any solution online or any article/thread/post that explained if this is even possible, I only always find the text that vite statically replaces the env variables at build time.

During our CI/CD pipeline vite gets the env variables but our Azure admins want to be able to configure them from Azure, just for the case of it.

Does anyone know if this is possible and or maybe has a solution or some help, please ? 🙂

7

Answers


  1. Chosen as BEST ANSWER

    My Solution is that it schould work with the links from my question. I use this approach and it works, the only thing that needs to be thought of is to use a different variable name/prefix (e.g. "APP_...") so vite doesn't change them at build time. I created a config file wich resolves the variable, for example if the app is in production than it uses the new Variable "APP_.."(which comes injected from nginx/ docker) or use "VITE_..."-variable if "APP_.." is undefined.


  2. You can set the variables in YAML format and update them accordingly as per your requirement.

    Below is the sample YAML format which we use as a template:

    #Set variables once
    variables:
      configuration: debug
      platform: x64
    
    steps:
    
    #Use them once
    - task: MSBuild@1
      inputs:
        solution: solution1.sln
        configuration: $(configuration) # Use the variable
        platform: $(platform)
    
    #Use them again
    - task: MSBuild@1
      inputs:
        solution: solution2.sln
        configuration: $(configuration) # Use the variable
        platform: $(platform)
    

    Check this SO for more insights to understand environment variables hosted in azure web app

    Login or Signup to reply.
  3. It is not possible to dynamically inject Vite env variables. But what is possible, is to change the window object variables (assign them on runtime).
    WARNING!!! DO NOT EXPOSE ANY SENSITIVE VARIABLES THROUGH THE WINDOW OBJECT. YOUR FRONT-END APPLICATION SOURCE IS VISIBLE TO ANYONE USING IT

    Steps:

    1. Create your desired env files and place them in <rootDir>/public. Let’s call them env.js and env-prod.js.

    2. Inside your env.js and env-prod.js You want to assign your desired variables using var keyword. Also, you will have to reference these values in your source like window.MY_VAR to be able to use them.

    3. Create a script tag inside your <rootDir>/index.html like this:
      <script type="text/javascript" src="./env.js"></script>.
      IMPORTANT!!! type="text/javascript" is important, because if You specify module, Vite will include your env.js source inside your minified index.js file.

    4. Vite config (optional):

      plugins: [react(), tsConfigPath()],
      build: {
        emptyOutDir: true, // deletes the dist folder before building
      },
    });
    
    1. How to serve the env files on runtime. Create a node server which will serve your frontend application. But before serving the env.js file, depending on our process.env.ENVIRONMENT you can now choose which env.js to serve. Let’s say my node server file is stored at <rootDir>/server/server.js:
    const express = require("express");
    const path = require("path");
    
    const app = express();
    
    const env = process.env.ENVIRONMENT || "";
    
    console.log("ENVIRONMENT:", env);
    
    const envFile = path.resolve("public", env ? `env-${env}.js` : "env.js");
    
    const indexFile = path.resolve("dist", "index.html");
    
    app.use((req, res, next) => {
      const url = req.originalUrl;
      if (url.includes("env.js")) {
        console.log("sending", envFile);
        // instead of env.js we send our desired env file
        res.sendFile(envFile);
        return;
      }
      next();
    });
    
    app.use(express.static(path.resolve("dist")));
    app.get("*", (req, res) => {
      res.sendFile(indexFile);
    });
    
    app.listen(8000);
    
    
    1. Serve your application build while running node ./server/sever.js command in your terminal.

    2. Finally:
      my env.js contains var RUNTIME_VAR = 'test'
      my env-prod.js contains var RUNTIME_VAR = 'prod'
      After I set my process.env.ENVIRONMENT to prod. I get this file served:
      enter image description here

    Login or Signup to reply.
  4. I came up with a solution and published it as packages to the npm registry.

    With this solution, you don’t need to change any code:

    // src/index.js
    console.log(`API base URL is: ${import.meta.env.API_BASE_URL}.`);
    

    It separate the build step out into two build step:

    During production it will be statically replaced import.meta.env with a placeholder:

    // dist/index.js
    console.log(
      `API base URL is: ${"__import_meta_env_placeholder__".API_BASE_URL}.`
    );
    

    You can then run the package’s CLI anywhere to replace the placeholders with your environment variables:

    // dist/index.js
    console.log(
      `API base URL is: ${{ API_BASE_URL: "https://httpbin.org" }.API_BASE_URL}.`
    );
    // > API base URL is: https://httpbin.org.
    

    Here is the documentation site: https://iendeavor.github.io/import-meta-env/.

    Feel free to provide any feedback.

    Login or Signup to reply.
  5. First create .env file in project root,then define a variable in .env

    e.g:VITE_APP_any = 'any'

    and then add following line to vite.config.js :

    export default defineConfig(({ command, mode }) => {
    
      const env = loadEnv(mode, process.cwd(), ""); //this line
    
      return { 
    .
    .
    .
    

    For usage can use following line

    import.meta.env.VITE_APP_any

    Or

    process.env.VITE_APP_any

    Login or Signup to reply.
  6. here is the Dockerfile

    FROM node:alpine3.14 AS buildJS
    WORKDIR /var/www/html
    COPY . .
    RUN apk add --no-cache yarn 
        && yarn && yarn build
    
    FROM nginx:stable-alpine
    WORKDIR /var/www/html
    COPY --from=buildJS /var/www/html/dist .
    COPY ./docker/conf/nginx.conf /etc/nginx/conf.d/default.conf
    COPY ./docker/conf/config.json /etc/nginx/templates/config.json.template
    
    ENTRYPOINT []
    
    CMD sleep 5 && mv /etc/nginx/conf.d/config.json config.json & /docker-entrypoint.sh nginx -g 'daemon off;'
    

    I’m building the project in the first stage without any envs,
    in the second stage I’m copying the files and then creating the config.json file based on envs that are passed at run time with envstub feature of nginx.

    then from the project I called the config.json file and load the envs from there but be careful you can not import it because imports will be resolved at build time instead you have to get it with fetch or axios or any equivalents

    Login or Signup to reply.
  7. // ./docker-compose.yml
    version: '3'
    services:
     front:
      /* some params */
      build:
       dockerfile: ./Dockerfile
       context: ./front
      env_file: .env // its important, no need environment
    
    // ./front/Dockerfile - do not use
    
    // ./.env
    // https://vitejs.dev/guide/env-and-mode.html
    // VITE_* prefix is needed
    VITE_SOME_VAR=value 
    
    // ./**/some_script.ts
    // Vite + Vue
    console.log('expected: ', import.meta.env.VITE_SOME_VAR) // expected: value
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search