Skip to main content

0005: Frontend Build and Configuration Strategy

Date: 2025-08-10

Status: Revised

Context

Frontend applications, such as the shell-app, need to connect to different backend environments (development, staging, production). Each environment has unique configuration values, such as API endpoints or feature flags.

A naive approach would be to use build-time environment files (e.g., Angular's environment.ts or a .env file with Vite). This would require building a separate container image for each environment, which violates the principle of a single, immutable build artifact that is promoted through environments. We need a strategy that decouples the build artifact from its runtime configuration.

Decision

We will adopt a runtime configuration model for all frontend applications.

  1. Build Process: Frontend applications will be built into a set of static assets (HTML, CSS, JS) using their standard toolchain (e.g., ng build).
  2. Serving: These static assets will be served by a lightweight web server (e.g., Nginx) within a Docker container. This container image is the single, immutable build artifact.
  3. Configuration File: The Nginx server will serve a special file at a known path, /assets/config.json. This file will contain all environment-specific variables.
  4. Configuration Loading:
    • The frontend application, upon startup, will make an HTTP request to fetch /assets/config.json.
    • This request must complete before the application fully bootstraps to ensure the configuration is available. Most modern frameworks provide a mechanism to block initialization until an asynchronous task (like fetching this file) is complete.
    • The loaded configuration will be stored in a dedicated, injectable service or a global state object.
  5. Configuration Provisioning:
    • The config.json file will not be baked into the container image.
    • In our Kubernetes environment, the configuration for each environment will be stored in a ConfigMap.
    • This ConfigMap will be mounted as a volume into the Nginx container at /usr/share/nginx/html/assets/config.json, effectively injecting the correct configuration at deploy time.

Consequences

Positive

  • Build Once, Deploy Anywhere: A single container image can be promoted across all environments (dev, staging, prod) without modification.
  • Decoupling: The build artifact is completely decoupled from the runtime environment. Configuration changes do not require a new build.
  • Security: Secrets and environment-specific details are managed by the deployment environment (e.g., Kubernetes), not stored in source code or build artifacts.
  • Consistency: All frontend applications will follow the same, predictable pattern for configuration.

Negative

  • Startup Latency: There is a small, one-time latency penalty on application startup due to the extra HTTP request to fetch the configuration file. This is considered an acceptable trade-off for the significant benefits.
  • Container Complexity: The Nginx container requires a simple entrypoint script to handle runtime substitutions, which adds a minor layer of complexity compared to a purely static container.