0

I have an angular application, which I need to build and scale for different clients, for each new client I need to create an environment.<client-name>.<prod-dev>.ts file and have to add some parameters for example

1. backend url
2. some api keys
3. some configurations flags etc... 

also I need to manage it in the angular.json and this is getting cumbersome really quick and also creating issues in CICD.

Any way ? that I can improve it ?

right now for example, for 3 clients, I will have 6 files to create i.e. development and production configurations and also provide build targets / configs in to angular.json

isoul
  • 1
  • 1
  • Have you thought about passing the clientId/name via environment variable and have `environment..ts` file some simple mapper logic to the correct configuration? It's for sure not beautiful, but at least you would not need to touch angular.json for a new client. – astoiccoder Jul 08 '23 at 20:54
  • You mean provide `fileReplacement` to cli from the environment variable ? – isoul Jul 24 '23 at 16:04
  • Something similar yeah, but I guess the main difficulty lies in the effect, that there is currently no easy way to pass environment variables to the application code. I'll write up an answer to show several options I came up with – astoiccoder Aug 05 '23 at 07:36

1 Answers1

0

The problem: Passing env variables (configurations) from cli

Team decided against adding this functionality in angular cli and possibility to define angular.json as .ts file (where you could use env variables during build) is also not given.

Possible options/workarounds:

Using @ngx-env/builder

Passing environment variables with NG_APP_ prefix, similar how it is done in react. To me this looked like the easiest solution, but I haven't used this one personally. Need to use custom builder from this lib "builder": "@ngx-env/builder:browser"

Custom script to write environment files

Use fs to do the fileReplacement dynamically with a set-env.js script and you can have your particular client configurations in that script that you read there and write the values into the environment.ts file. Slightly different version, using dotenv as well

Custom webpack builder

Using @angular-builders/custom-webpack and webpack DefinePlugin and spawn ng serve as a child process. That way you can pass an environment variable that determines which client configuration to use

Pass environment variables with angular-server-side-configuration

https://github.com/kyubisation/angular-server-side-configuration

Replace environment files for clients in your deployment tools

Load a specific file that you are replacing in any way during your deployment process and load them via APP_INITIALIZER in your app module:

{
  provide: APP_INITIALIZER,
  useFactory: async () => {
    try {
      // Dynamically import the client-specific environment
      const clientEnvironment = await import(
        `../config/${clientConfig.ts}`
      ).then((mod) => mod.environment);
      return { ...clientEnvironment };
    } catch (error) {
      console.log(error);
      // If the client-specific environment file doesn't exist, use the default environment
      return {};
    }
  },

Using window as a workaround

Have an env.js file for each client - similar to the solution above where your deployment process would replace the env.js file with the specific client configuration.

Have a angular.ts file and transform it to angular.json via script

In the angular.ts file you could then import the desired client configurations based on an environment variable you pass, e.g. CLIENT_ENV=<client-name><env>. This .ts file you then need to transform to angular.json before your build.

Wrap up

Hopefully this can give you some inspiration on how to solve this issue with angular cli.

Since you wrote that you have api keys in those client environment files as well, just be aware that all those values are readable by anyone accessing your application and that these keys should not contain sensitive information.

astoiccoder
  • 143
  • 5