web-dev-qa-db-fra.com

Passez la variable d'environnement dans une application Vue lors de l'exécution

Comment puis-je accéder aux variables d'environnement dans Vue, qui sont transmises au conteneur au moment de l'exécution et non pendant la génération?

La pile est la suivante:

  • VueCLI 3.0.5
  • Docker
  • Kubernetes

Il existe des solutions suggérées sur stackoverflow et ailleurs pour utiliser le fichier .env pour passer des variables (et en utilisant le mode), mais c'est au moment de la construction et est intégré dans l'image du docker.

Je voudrais passer la variable dans Vue au moment de l'exécution comme suit:

  • Créer Kubernetes ConfigMap (je comprends bien)
  • Passez la valeur ConfigMap dans la variable env du pod K8s lors de l'exécution du fichier yaml de déploiement (je comprends bien)
  • Lire à partir de la variable env créée ci-dessus, par exemple. VUE_APP_MyURL et faire quelque chose avec cette valeur dans mon Vue App (je ne comprends pas bien))

J'ai essayé ce qui suit dans helloworld.vue:

<template>
<div>{{displayURL}}
  <p>Hello World</p>
</div>
</template>
<script>
export default {  
        data(){
            return{
                displayURL:""
        }
    },
    mounted(){
        console.log("check 1")
        this.displayURL=process.env.VUE_APP_ENV_MyURL
        console.log(process.env.VUE_APP_ENV_MyURL)
        console.log("check 3")
     }
}
</script>

Je reviens "indéfini" dans le journal de la console et rien ne s'affiche sur la page helloworld.

J'ai également essayé de passer la valeur dans un fichier vue.config et de la lire à partir de là. Même résultat "indéfini" dans console.log

<template>
<div>{{displayURL}}
  <p>Hello World</p>
</div>
</template>
<script>
const vueconfig = require('../../vue.config');
export default {  
        data(){
            return{
                displayURL:""
        }
    },
    mounted(){
        console.log("check 1")
        this.displayURL=vueconfig.VUE_APP_MyURL
        console.log(vueconfig.VUE_APP_MyURL)
        console.log("check 3")
     }
}
</script>

Avec vue.config ressemblant à ceci:

module.exports = {
    VUE_APP_MyURL: process.env.VUE_APP_ENV_MyURL
}

Si je code en dur une valeur dans VUE_APP_MyURL dans le fichier vue.config, elle s'affiche avec succès sur la page helloworld.

VUE_APP_ENV_MyURL est correctement renseigné avec la valeur correcte lorsque je l'interroge: kubectl describe pod

process.env.VUE_APP_MyURL ne semble pas récupérer correctement la valeur.

Pour ce que ça vaut ... Je peux utiliser process.env.VUE_APP_3rdURL avec succès pour transmettre des valeurs dans une application Node.js lors de l'exécution.

15
Johann

J'ai eu le même problème dans mon projet actuel et j'ai découvert qu'il n'était pas possible d'accéder aux variables d'environnement au moment de l'exécution, donc je me retrouve avec la solution de créer des fichiers .env ou des variables d'environnement locales qui, comme vous l'avez dit, sont utilisées au moment de la construction.

5
José Silva

Créez un fichier config.js avec la configuration souhaitée:

const config = (() => {
  return {
    "VUE_APP_ENV_MyURL": "...",
  };
})();

Assurez-vous que votre script est exclu du grossissement afin que nous puissions y monter quelque chose plus tard. Créez un fichier vue.config.js avec le contenu suivant:

const path = require("path");
module.exports = {
  publicPath: '/',
  configureWebpack: {
    module: {
      rules: [
        {
          test: /config.*config\.js$/,
          use: [
            {
              loader: 'file-loader',
              options: {
                name: 'config.js'
              },
            }
          ]
        }
      ]
    }
  }
}

Dans votre index.html, ajoutez un bloc de script pour charger le fichier manuellement:

`<script src="config.js"></script>

Modifiez votre code pour utiliser la configuration d'exécution:

this.displayURL = config.VUE_APP_ENV_MyURL || process.env.VUE_APP_ENV_MyURL 

Dans Kubernetes, créez une carte de configuration comme celle-ci:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  config.js: |
    var config = (() => {
      return {
        "VUE_APP_ENV_MyURL": "...",
      };
    })();

... et utilisez-le dans votre déploiement:

apiVersion: apps/v1
kind: Deployment
metadata:
 ...
spec:
  ...
  template:
    ...
    spec:
      volumes:
        - name: config-volume
          configMap:
            name: ...
      containers:
        - ...
          volumeMounts:
                - name: config-volume
                  mountPath: /usr/share/nginx/html/config.js
                  subPath: config.js
1

J'ajoute ma solution de travail ici, pour ceux qui ont encore des problèmes. Je pense que la réponse de @Hendrik M Halkow est plus élégante, même si je n'ai pas réussi à le résoudre en utilisant cela, simplement en raison de mon manque d'expertise dans le webpack et Vue.Je n'arrivais pas à comprendre où mettre le fichier de configuration et comment s'y référer.

Mon approche consiste à utiliser les variables d'environnement avec des constantes (valeurs fictives) pour le construire pour production, puis remplacer ces constantes dans l'image à l'aide d'un script personnalisé entrypoint. La solution va comme ça.

J'ai encapsulé toutes les configurations dans un fichier appelé app.config.js

export const clientId = process.env.VUE_APP_CLIENT_ID || $VUE_APP_CLIENT_ID;
export const baseURL = process.env.VUE_APP_API_BASE_URL || $VUE_APP_API_BASE_URL;

export default {
  clientId,
  baseURL,
};

Ceci est utilisé dans le projet simplement en recherchant la valeur du fichier de configuration.

import { baseURL } from '@/app.config';

Ensuite, j'utilise des fichiers standard . Env. [Profile] pour définir les variables d'environnement. par exemple. le .env.development

VUE_APP_API_BASE_URL=http://localhost:8085/radar-upload
VUE_APP_CLIENT_ID=test-client

Alors pour production je mets constantes de chaîne comme valeurs. par exemple. le .env.production

VUE_APP_API_BASE_URL=VUE_APP_API_BASE_URL
VUE_APP_CLIENT_ID=VUE_APP_CLIENT_ID

Veuillez ne pas ici la valeur peut être n'importe quelle chaîne unique. Juste pour garder la lisibilité plus facile, je remplace simplement le nom de la variable d'environnement comme valeur. Cela sera simplement compilé et regroupé comme dans le mode de développement.

Dans mon Dockerfile, j'ajoute un entrypoint qui peut lire ces constantes et le remplacer par des valeurs de variables d'environnement.

Mon Dockerfile ressemble à ceci (c'est assez standard)

#Alpine version close to the version mentioned in the readme
FROM node:10.16.3-Alpine as builder

RUN mkdir /app
WORKDIR /app

COPY ./radar-upload-frontend/package*.json /app/
RUN npm install

COPY ./radar-upload-frontend/ /app/

RUN npm run build --prod


FROM nginx:1.17.3-Alpine

WORKDIR /usr/share/nginx/html

COPY --from=builder /app/dist/ .

COPY ./docker/frontend-entrypoint.sh /entrypoint.sh

# expose internal port:80 and run init.sh
EXPOSE 80

CMD ["/entrypoint.sh"]

Créez ensuite un fichier ./ docker/frontend-entrypoint.sh comme ci-dessous.

#!/bin/sh

# Replace env vars in JavaScript files
echo "Replacing env constants in JS"
for file in /usr/share/nginx/html/js/app.*.js*;
do
  echo "Processing $file ...";

  sed -i 's|VUE_APP_API_BASE_URL|'${VUE_APP_API_BASE_URL}'|g' $file 
  sed -i 's|VUE_APP_CLIENT_ID|'${VUE_APP_CLIENT_ID}'|g' $file

done

echo "Starting Nginx"
nginx -g 'daemon off;'

Cela me permet d'avoir une image configurable à l'exécution que je peux exécuter sur de nombreux environnements. Je sais que c'est un peu un hack. Mais j'ai vu beaucoup de gens le faire de cette façon.

J'espère que cela aide quelqu'un.

0
NehaM