Managing environment variables in Angular apps
Tags: webdev, angular, environmentvariables, deployment
Published: 2024-07-02 12:18:58

Some days ago I had to initialise a new **Angular app** for a side project of mine. The use case would be fairly simple, and I needed some basic features like user authentication and some entities to store on a backend.

In such cases [Supabase](https://supabase.com/) is a great open-source alternative to setting up a custom backend, and integrating it into an Angular app is fairly simple, given the existing supabase dependencies like [@supabase/supabase-js](https://github.com/supabase/supabase-js). The only prerequisite to make it work is **initialising a supabase project** and **generating an API key**.

However, I found out that managing environment variables in an Angular project is not really straight forward. Once we generate a project via the Angular CLI, we get the `environment.ts` and `environment.prod.ts` files, but these cannot be used for declaring such API keys, especially if we want to push our codebase to a github repository.

After some research I did, I discovered [@ngx-env/builder](https://www.npmjs.com/package/@ngx-env/builder) which, as it seems, provides us with a clean and secure way to store our environment variables.

You can find a sample project showcasing how it works here: 

{% github dimeloper/angular-environment-variables %}

## Getting started

Once we are at our Angular project root directory we can simply run `ng add @ngx-env/builder` to get started. This command will install the necessary dependency, adjust the application builders accordingly and generate the environment types within `env.d.ts`.

Once this is complete we can extend the generated `env.d.ts` and its Env interface with our expected environment variables. For example:

```ts
declare interface Env {
  readonly NODE_ENV: string;
  // Replace the following with your own environment variables.
  readonly NG_APP_ENV: string;
  readonly NG_APP_PUBLIC_SUPABASE_URL: string;
  readonly NG_APP_PUBLIC_SUPABASE_ANON_KEY: string;
}
```

Please keep in mind that the `NG_APP_` prefix **is mandatory**. In case you need to change it please consult the related [documentation](https://github.com/chihab/dotenv-run/tree/main/packages/angular#ng_app_-or-custom-prefix).

## Defining Environment Variables

Now we can use `.env` files on our local and production environments with the corresponding values. First we need to make sure that our `.gitignore` includes the `.env` file. Then we can create our local `.env` file as such:

```env
NG_APP_PUBLIC_SUPABASE_URL=https://test.supabase.co
NG_APP_PUBLIC_SUPABASE_ANON_KEY=keykeykeyvaluevalue
```

Since we included this file as part of our `.gitignore`, these values won't be pushed to our github repository.

## Usage in components / templates

We can import the actual values of our environment variables in our components as such:

```ts
supabaseUrl = import.meta.env.NG_APP_PUBLIC_SUPABASE_URL;
```

Basically the `import.meta.env` object will include all the environment variables we've defined.

## Differentiate environments across serve and build tasks

We could possibly use the default `NODE_ENV` values to differentiate between e.g. `development` and `production` environments, however I prefer having my own app environment values which for this sample project, I've defined within `package.json`.

Example:

```json
"scripts": {
  "start:dev": "NG_APP_ENV=dev ng serve",
  "start:staging": "NG_APP_ENV=staging ng serve",
  "start:production": "NG_APP_ENV=production ng serve",
  "build": "NG_APP_ENV=production ng build"
}
```

By doing this we have a **clear app environment separation**, while we are also able to differentiate pieces of implementation depending on the app environment, e.g. if we want to show a teaser component only on production or staging.

## Deployment / usage in production

Once our local setup is complete, we can overwrite the values of our environment variables, just by defining them on the staging/production system environment (e.g. `export NG_APP_PUBLIC_SUPABASE_URL="environment.specific.url"`), or by creating an `.env` file in there, including all the enviroment specific values (e.g. staging values on the testsystem, production values on the live server).

## Conclusion

Managing API keys and secret values that should be handled as environment variables is an essential part of any frontend application that should be production ready. The [@ngx-env/builder](https://www.npmjs.com/package/@ngx-env/builder) package provides us with an elegant and straightforward way to do so, when it comes to Angular apps. Enjoy!