Skip to the solution
EasyFrontend8 min read

How do you configure dynamic base href in Angular builds for different environments?

623 views

The problem

Question presented to candidate: "The same Angular app is deployed at / in production, at /staging/ on a shared host, and at /tenant-name/ for some customers. How do you make it work everywhere, ideally without a separate build per tenant?"

What a strong answer should cover:

  • The base href is the <base href> tag in index.html; the browser resolves every relative URL (scripts, styles, assets) against it, and the router uses it as the app's root path.
  • Build-time options: ng build --base-href /staging/, or a baseHref per configuration in angular.json (ng build -c production,staging).
  • Only index.html changes; the JavaScript bundles are byte-identical, so one build can be deployed under many paths by rewriting the tag at deploy time.
  • Runtime option for the router: provide APP_BASE_HREF (it wins over the DOM tag), but it does not change how the browser loads relative asset URLs.
  • The value needs a trailing slash: /shop resolves main.js to /main.js.
  • deployUrl is a different thing: it prefixes asset URLs (for a CDN) and leaves <base href> alone. The server must also fall back to index.html for deep links.

Clarifying questions expected:

  • "Is the path known at build time, or only when the container starts or the request arrives?"
  • "Are assets served from the same origin, or a CDN?"

Code / implementation expected: Yes β€” build configurations in angular.json, and an APP_BASE_HREF factory for a runtime path.

  • build
  • cli

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 10 sections

Read the code

AngularRuntime base path for the router with an APP_BASE_HREF factory
import { APP_BASE_HREF, Location, PlatformLocation } from "@angular/common";
import { ApplicationConfig, Component, inject } from "@angular/core";
import { provideRouter, RouterLink, RouterOutlet } from "@angular/router";

// Stand-in for a deploy-time env.js (loaded before main.js) that the server writes per environment:
//   window.__env = { baseHref: "/tenant-42/" };
(window as any).__env ??= { baseHref: "/tenant-42/" };

@Component({ selector: "app-orders", template: `<p>orders page</p>` })
export class OrdersComponent {}

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter([{ path: "orders", component: OrdersComponent }]),
    // Runtime base href for the router. Wins over the <base href> tag that ng build wrote.
    { provide: APP_BASE_HREF, useFactory: () => (window as any).__env?.baseHref ?? "/" },
  ],
};

@Component({
  selector: "app-root",
  imports: [RouterLink, RouterOutlet],
  template: `
    <a routerLink="/orders">Orders</a>
    <router-outlet />
    <p>base tag in DOM: {{ domBase ?? "none" }}</p>
    <p>external url for /orders: {{ external }}</p>
  `,
})
export class AppComponent {
  domBase = inject(PlatformLocation).getBaseHrefFromDOM();
  external = inject(Location).prepareExternalUrl("/orders");
}
Angularangular.json build configurations for a staging base href and a CDN deploy URL
// angular.json (excerpt): projects.demo.architect.build.configurations
// Built with: ng build -c production,staging   and   ng build -c production,cdn
{
  "production": {
    "budgets": [
      { "type": "initial", "maximumWarning": "500kB", "maximumError": "1MB" },
      { "type": "anyComponentStyle", "maximumWarning": "4kB", "maximumError": "8kB" }
    ],
    "outputHashing": "all"
  },
  "staging": {
    "baseHref": "/staging/"
  },
  "cdn": {
    "deployUrl": "https://cdn.example.com/app/"
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 5 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextEasy

What are components and modules in Angular?

Continue