Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading server environment variable in Angular at runtime

Tags:

docker

angular

I am new into angular. I have deployed an angular app into a docker container in aws. The app needs to connect to aws s3 bucket. I dont need to hardcode the aws key so I setup an environment variable in the docker. the angular is deployed such that the dist folder from the ng build is served by an nginx docker container.

Is it possible to read the server environment variable by the angular once the contents from the dist folder is served into the server? like env function in php and nodejs

like image 277
sandeep krishna Avatar asked Sep 02 '25 06:09

sandeep krishna


2 Answers

Unfortunately there is no way to read an environment variable in Angular similar to mechanisms that server frameworks like nodejs or Spring Boot offer.

You could however load the environment from the server before the Angular app bootstraps (please read the drawbacks below before taking this path).

Load environment variables from a server:

  • Remove the bootstrap component from your root module (e.g. AppModule) so that it is not bootstrapped automatically
  • Create a singleton service in root that loads the environment variables, e.g:
import { Injectable } from "@angular/core";

@Injectable({ providedIn: "root" })
export class EnvService {
  public myEnv: string;

  fetchEnv() {
    // This has to retrieved from some server.
    return fetch("some-url").then(env => {this.myEnv = env.myEnv; return Promise.resolve("env loaded");};
  }
}
  • Delay the bootstrap in your root module until the environment is loaded:
@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent, HelloComponent]
})
export class AppModule {
  constructor(private envService: EnvService) {}
  ngDoBootstrap(app) {
    this.envService.fetchEnv().then(() => app.bootstrap(AppComponent));
  }
}

This approach has a couple of drawbacks:

  • The url from where to retrieve the env settings has to be known before loading the other env variables
  • The Angular app will not boot if the environment variables can't be loaded. As you are using Docker, you could host a small web server inside the Docker container that provides the environment variables on a dedicated endpoint for the Angular app. However this might come with its own problems, as this makes creating your Angular Docker container more complicated.

I would therefore recommend configuring the env variables during the build.

There are 2 ways you can set the environment variables during the build:

1) Set the environment variable in the build using a custom webpack config

See this article.

You can specify a custom webpack config in your angular.json:

"architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "extra-webpack.config.js"
            },
...

The webpack config file would look like this:

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        // Here you can set your env variables.
        SERVER_URL: JSON.stringify(process.env.SERVER_URL)
      }
    })
  ]
}

This method requires some more dependencies:

@angular-builders/custom-webpack
dotenv

2) Dynamically create an environment file during build

See e.g. the automatically generated src/environments/environment.prod.ts. You could generate this file with the correct environment values or replace placeholders in this file during the build.

Edit: See also The Fabio's answer. You probably don't want your users to be aware of the S3 bucket anyway and should route your request over a web server to the bucket if possible.

like image 111
code-gorilla Avatar answered Sep 04 '25 21:09

code-gorilla


I know this is an old question, but I wanted to add a potential option for anyone searching for this.

If you are deploying your Angular app in a Docker container using NGinx or something similar, I used a tool called confd by @kelseyhightower here https://github.com/kelseyhightower/confd .

Basically modifying index.html so it had confd template variables in it, that create a "config" object that is then accessible in your Angular code. You could then use the values in that "config" object to set your environment.ts values. Confd would need to be set up to run on container start.

This would be added to the end of your Dockerfile Dockerfile config

This would be added to your index.html file. index.html config

This is the start script for the container. I copy it into /usr/local/bin as part of my Dockerfile steps. start.sh script

Access the values in your environment.ts file environment.ts

Worked well for me so far, but you may need to find an alternate solution for deployments that are not Container based.

like image 32
Ben H Avatar answered Sep 04 '25 23:09

Ben H