Generator-jhipster: dynamic environment variables

Created on 22 May 2019  Â·  31Comments  Â·  Source: jhipster/generator-jhipster

Overview of the feature request


I would like to be able to change front-end variables directly by edit a config file instead of having to rebuild the whole app

Motivation for or Use Case

Having the same war/docker image for all environments

Here is an example detailing how we could implement it:
https://www.jvandemo.com/how-to-use-environment-variables-to-configure-your-angular-application-without-a-rebuild/

Related issues or PR

  • [x] Checking this box is mandatory (this is just to show you read everything)

$$ bug-bounty $$ $100 area front

Most helpful comment

@vishal423 there should be no sensitive data in any js file that is common sence, all js is shipped to the clients.
The way I use it is:
I have a dev (local) test(server) prod(server) environments, using kubernetes on my servers.
with the current jhipster (without env.js) I can't use the same build/war/dockerImage for both test and prod, as all constants are hard coded at build time.
With the env.js, I can supply a different env.js per environment and use the same build for image for both of them (for anyone interested in k8s configMap do the trick).

All 31 comments

The crux of that article deals with separate front end deployment, whereas the default Jhipster behavior is to encapsulate both frontend and backend deployment artifacts inside a jar. Using advance flags (skip server), you can have separate frontend artifacts, but, not sure how many users use that option.

It would be good to understand the configurations that you believe should be exposed as default In Jhipster. IMO, before we proceed, we should evaluate the usefulness of this feature.

@vishal423 I am using this feature in the gateway without the skip-server option, it allows me to configure the my front-end on angular startup without having to store the variables in application.yml and having request sent an http request sent to retrieve the info (much faster), it also allows separation of concerns...

@yelhouti, If I understood correctly, then, you are using this during development. When frontend artifacts are encapsulated in a jar/war, can you elaborate more on how do you configure these variables?

Also, if your configurations contain any sensitive information, then, I see that as a security issue as this external js can be accessed directly as URL.

@vishal423 there should be no sensitive data in any js file that is common sence, all js is shipped to the clients.
The way I use it is:
I have a dev (local) test(server) prod(server) environments, using kubernetes on my servers.
with the current jhipster (without env.js) I can't use the same build/war/dockerImage for both test and prod, as all constants are hard coded at build time.
With the env.js, I can supply a different env.js per environment and use the same build for image for both of them (for anyone interested in k8s configMap do the trick).

I think it is something which could be nice to have.
What do you think @wmarques ?

Then, if @wmarques agrees : who wants to do this ? @yelhouti @vishal423 ?
Don't forget the Vue.js blueprint part, too.

@pascalgrimaud I can do the angular part

I'm ok with it, indeed it's a nice thing to have env variable on client-side.
I would go for a JSON file rather than a JS one. WDYT ?

@yelhouti if you want to start on the angular part please go ahead :)

@wmarques it's not really a js file it looks in my case like this:

window.__env = window.__env || {};
window.__env.keycloakUrl = 'http://keycloak:9080';
window.__env.keycloakClockSkew = 10;

Why? because it is valid js and interpreted without angular intervention, it's accepted as a configMap by kubernetes. if you havea json way that work for both I'm ok with it.
what do you think?

I'm ok with that approach, not an expert with k8s so I trust you :)

If we have decided to proceed on this, then, I will prefer doing it with JSON instead of updating the window object, which is considered a bad practice. A good approach to do that can be found @ https://www.technouz.com/4746/how-to-use-run-time-environment-variables-in-angular/

@vishal423 most of these env variables a required to bootstrap angular (ie: before angular starts), to define the IdP Url..., having them stored in one __env file is not that bad and works cross framework...
Making them accessible only through and angular service narrows there scope and usability...

@yelhouti, I believe it loads these during angular bootstrapping and these are available to use in other angular services/components via dependency injection. Can you elaborate more on why do you think that the use of angular services reduce usability?

@vishal423 as you mentionned, these variable will only be available inside angular using the service, imagine I have some iframe (an authentication helper https://openid.net/specs/openid-connect-session-1_0.html) that I want included directly in my HTML, but with a different URL whether I'm in prod or test. I want to put the iframe directly in my index.html, this iframe should check if I'm authenticated even before angular loads. Using the service it would be a total mess.
If you want your variables only through a service you could that, but Env variables are much more than that and should have a much higher scope.

@yelhouti, I understand that using angular services to share constants/variables may not be appropriate for your scenario, but, that's not what JHipster supports out of the box. Also, anything attached to the window object is a global variable (the equivalent of using var outside functions). I wouldn't suggest to have this by default in JHipster and promote a bad practice.

@vishal423, these are supposed to be env variables, with env standing for environement, ie, accessible from everywhere...
Another raison to put them outside the code is being able to mount the file and access it, and it would worse I think to inject the httpClient, request the file, parse it, then initialize you app. TTI (time to interactive) would suffer a lot.

If we are doing it for angular, we should do it for React as well

On Tue, 4 Jun 2019, 8:54 pm yelhouti, notifications@github.com wrote:

@vishal423 https://github.com/vishal423, these are supposed to be env
variables, with env standing for environement, ie, accessible from
everywhere...
Another raison to put them outside the code is being able to mount the
file and access it, and it would worse I think to inject the httpClient,
request the file, parse it, then initialize you app. TTI (time to
interactive) would suffer a lot.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/9778?email_source=notifications&email_token=AAIOKFYJ4LE4445RIP4HW5TPY226LA5CNFSM4HOUEKCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODW5Q3IY#issuecomment-498797987,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAIOKF5VZYXCKYWL6JHESKLPY226LANCNFSM4HOUEKCA
.

If we want a homogenous support for the three frontend frameworks, then @yelhouti is the best solution as it's framework agnostic.
We can add an Angular service to wrap this so we can access the env variables inside Angular easily without accessing to the window object.

Indeed, I'm not a big fan of that way as I find a JSON file more readable and I also do not like to put things in window...

@sahbi-ktifa @hdurix WDYT about this ? Is it better to load an env file with "plain" JS in the window object or to load it once the framework as started using framework features ?

For me this is only halfway through what I want because I would like to be able to set the env variables for both the back-end and front-end through regular spring properties. Also as far as I understood your implementation is not able to read system environment variables and set them in the angular context.
I wish there was a real property management lib in js that we could use for all 3 frameworks.

@PierreBesson for the backend part, application.yml/application.prod.yml already solves that problem, this files could be modified in production in order to change the behavior of the backend.

You don't want to read the env.js properties from a spring endpoint. this would require to send a request and interpret the answer (in angular case, this would work only after angular is loaded)

The way it is done today, this variables can be used to modify angular behavior, and cover a much more general use case.

modifying env variables is as simple as modifying the env.js file, bit the env.js file doesn't require any fancy code/libraries.

I have been using this design production for many months/projects, and is not something I though of just today (I just didn't have time to implement before, + the bounty fixed my priorities :p) .

If you have a use case this solution doesn't work with, please comment below and I will be happy to discuss it with you.

@yelhouti I'm not sure you understood my point. I think it's because environment variable means different things for us. For me it's something like ENV_VAR that I can set for docker containers (I'm mostly concerned with the devops side as I'm now doing this full time in my current job). So from this point of view I would find it useful to set a property value for both front end and backend.
Initially I was doing this myself using the spring boot /info endpoint in which you can inject properties by setting something like info.some.variable=value in application.yaml or through setting INFO_SOME_VARIABLE system env vars.

@PierreBesson Oh I see, but why are you trying to use env variables, aren't config maps much better for this usecase?

Well the property can come from a configmap but my current way to do it is to always inject by env var. Also I have to manage secrets and config properties shared accross multiples services.

Personally, I think that something that specific for your use case should not be added to JHipster, but I might be wrong, so your call...

I would very much like this to be a feature too. This is a fundamental part of a normal Vue application so why leave it out for Jhipster.
Use case: use environment variables to change out properties like google analytics, iframes etc for local, development and production environments.
I now used a workaround where I make a get request to actuator endpoint to fetch the current profiles and hardcoded the properties.

I think ideally we need both mechanisms. Also, @yelhouti's use case seems to be the most frequent among front-end developers (I see something similar to this in my current project). So I'm in favor of merging @yelhouti's PR. Sorry if the discussion is taking too long. Please understand that we already made mistakes in the past by being too eager to add new features and it's not possible to roll back afterward... @wmarques do you agree with this ?

@PierreBesson I hesitated a lot before making the PR and I totally agree, this is really on the border of what may be acceptable in JHipster, I would not mind at all if the majority agrees that this should not be merged. So please, take all the time needed.

Seeing your perseverance and good argumentation, I'm changing my mind and support your idea. However, it should be implemented consistently between angular, react and vue.

It is already implemented for both angular and react, i think vue is not in this repo (and have never written vue code so...) Also I think some test should be fixed so I will let you know when it's done

I'm ok to merge this, let's go ahead :) It's a good starting point to have dynamic env variables which I agree is very useful in alot of projects.

Sorry @yelhouti for the time and thanks for your patience

EDIT: seems that you have failing CI so we can merge it once CI is ok

@yelhouti, I have provided few comments in the associated PR. I will leave the decision to incorporate / defer those to @wmarques

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomj0101 picture tomj0101  Â·  3Comments

frantzynicolas picture frantzynicolas  Â·  3Comments

kaidohallik picture kaidohallik  Â·  3Comments

trajakovic picture trajakovic  Â·  4Comments

RizziCR picture RizziCR  Â·  3Comments