DEV Community

Mathias Remshardt
Mathias Remshardt

Posted on

File replacements when building angular projects

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:

{
  "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"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Folder structure for file replacement

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.
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 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

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:

{
  "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"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

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

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.

Top comments (2)

Collapse
 
akbbhatt profile image
Anil Balachandra

Do you think this will work for ng e2e? Apparently, I could not find any solution for replacing files when executing e2e tests.

Collapse
 
remshams profile image
Mathias Remshardt • Edited

Have not tested/used it for the e2e target to be honest (e2e is done with Selenium in the project the approach is in use).
So do I get you right that the file is not copied/replaced at all for the e2e target?

If that is the case the approach will unfortunately not work as it relies on the configuration.json being copied to the destination.