File replacements when building angular projects
Tags: angular, question
Published: 2021-01-16 17:11:01

---
title: File replacements when building angular projects
published: true
description: File replacement in angular builds using assets instead of file replacements
tags: angular, question
---

This short article is about replacing files (e.g. configuration files) for different build configurations/targets (like `dev`, `qa` and `prod`) in Angular. For our projects we used to leverage the Angular file replacements feature to provide different files based on the chosen build target:

```json
{
  "production": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      },
      {
        "replace": "src/configurations/configuration.json",
        "with": "src/configurations/configuration.prod.json"
      }
    ]
  },
  "dev": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.dev.ts"
      },
      {
        "replace": "src/configurations/configuration.json",
        "with": "src/configurations/configuration.dev.json"
      }
    ]
  },
  "qa": {
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.qa.ts"
      },
      {
        "replace": "src/configurations/configuration.json",
        "with": "src/configurations/configuration.qa.json"
      }
    ]
  }
}
```

![Folder structure for file replacement](https://github.com/remshams/angular-file-replacement/blob/assets/images/folder-structure-replacement.png?raw=true)

However, file replacements outside of bundles were never officially supported by Angular and has ceased to work since the Angular 9 release as described [here](https://github.com/angular/angular-cli/issues/16779).
We have migrated to the proposed workaround in the linked Github issue and it is working fine for us so far. In case someone has the same issue/question (and also to document the approach for myself ;) ), I have created a [simple example repository](https://github.com/remshams/angular-file-replacement) showcasing the approach for a single `configuration.json` file.
The following section shows the required steps.

# Configuration Folder

In the example, a dedicated folder holding the different configurations has been created. This is not necessarily required but keeps the files organized. Next, each configuration target has an associated folder containing the `configuration.json`. The additional folder is indeed required as otherwise it is not possible to select and copy the correct file (described in the next section).
At the end it looks something like the following:

![Folder structure for file assets replacement](https://github.com/remshams/angular-file-replacement/blob/assets/images/folder-structure-assets.png?raw=true)

# Angular CLI configuration file (angular.json)

As shown in the snippet below, for each of the deployment configurations the associated `configuration.json` is copied as part of the `assets` section:

```json
{
  "production": {
    "assets": [
      "src/favicon.ico",
      "src/assets",
      {
        "input": "src/configurations/prod",
        "output": "configuration/",
        "glob": "*.json"
      },
      {
        "input": "src/configurations",
        "output": "configuration/",
        "glob": "README.md"
      }
    ],
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ]
  },
  "dev": {
    "assets": [
      "src/favicon.ico",
      "src/assets",
      {
        "input": "src/configurations/dev",
        "output": "configuration/",
        "glob": "*.json"
      },
      {
        "input": "src/configurations",
        "output": "configuration/",
        "glob": "README.md"
      }
    ],
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.dev.ts"
      }
    ]
  },
  "qa": {
    "assets": [
      "src/favicon.ico",
      "src/assets",
      {
        "input": "src/configurations/qa",
        "output": "configuration/",
        "glob": "*.json"
      },
      {
        "input": "src/configurations",
        "output": "configuration/",
        "glob": "README.md"
      }
    ],
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.qa.ts"
      }
    ]
  }
}
```

By means of the created subfolders in the configuration folder, the correct `configuration.json` file can be selected and copied. With help of the `output` property the path within the `dist` folder is defined. For the example, it is copied to a configuration folder in the root path. In addition a `README.md` is put next to the `configuration.json` to describe its properties and their effect on the application. Creating the dedicated folder helps to keep the two files next to each other.

![Angular dist folder with configuration files](https://github.com/remshams/angular-file-replacement/blob/assets/images/dist-folder.png?raw=true)

What I don't like about the approach is, that we now have to duplicate the `assets` properties for all build configurations as otherwise e.g. the `assets` folder (images, fonts, translations and the like) does not get copied. Also, having to create a dedicated subfolder is also not as convenient as it was with the file replacement (although this is more a nuisance than a major drawback).

In case you have a better idea (or a solution) for solving the duplication, I'd love to hear about it. Otherwise I hope it can be beneficial for someone.