Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set the Angular base path programmatically prior to initialization?

Tags:

angular

cdn

Background / Goal

  • I have an app with multiple environments, each stored in a subfolder of a CDN.
    • e.g. cdn.com/dev, cdn.com/test
  • My goal is to load the dev site (cdn.com/dev/index.html) and have it load the corresponding resources from the /dev/ path.

⚠️ℹ️ We are doing a build-once, deploy-many strategy, so I do not have the ability to pass the baseHref as part of a build process or similar.

The Problem

So far no matter what I've tried, cdn.com/dev/index.html attempts to load scripts from the root (cdn.com/script.js) instead of the subfolder (cdn.com/dev/script.js)

What I've Tried

❌ Attempt 1: Set APP_BASE_HREF and use it as a provider

I set a window variable in index.html:

<script>
    window['base-href'] = window.location.pathname;
    console.log(window['base-href']);
</script>

Then I attempt to use that value to pass to APP_BASE_HREF as part of the provider, in app.module.ts:

import { APP_BASE_HREF } from '@angular/common';
let baseHref = (window as { [key: string]: any })["base-href"] as string;

if (!baseHref.endsWith("/")) {

  baseHref += "/";

}

// I only updated the providers array below
@NgModule({
  declarations: [
    AppComponent,
    ComingSoonListComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule
  ],
  providers: [
    {
      provide: APP_BASE_HREF,
      useValue: baseHref
    }
  ],
  bootstrap: [AppComponent]
})

This did not appear to work.

❌ Attempt 2: A slightly less naive attempt

I remove the base tag from the index.html page on the off-chance it's overriding things.

In index.html, I call the script to capture the pathname:

<script>
    window['base-href'] = window.location.pathname;
    console.log(window['base-href']);
  </script>
</

In app.module.ts, I create a factory method that captures the window value, and then use it:

const baseHrefFactory = () => {
  let baseHref = (window as { [key: string]: any })["base-href"] as string;
  if (!baseHref.endsWith("/")) {

    baseHref += "/";

  }
  console.log('TS: using baseHref of:', baseHref);
  return baseHref;
}

// Note I just use the factory method below

@NgModule({
  declarations: [
    AppComponent,
    ComingSoonListComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
  ],
  providers: [{ provide: APP_BASE_HREF, useFactory: baseHrefFactory }],
  bootstrap: [AppComponent],
})
export class AppModule { }
  • I can see the window value being set (per console logging)
  • It appears other files try to load before we can programmatically trigger the APP_BASE_HREF factory, and are attempted to load from the root path rather than the path I'd set. When running locally, it appears to work fine, but likely only because the path is / naturally.

❌ Attempt 3: Set the base href directly in HTML

In index.html in the <head> tag, after the base tag has been created:

  <script>
    var baseHref = window.location.pathname;
    if (!baseHref.endsWith("/")) {
      baseHref += "/";
    }

    console.log("setting a baseHref of:", baseHref);
    document.getElementsByTagName("base")[0].href = baseHref;
  </script>
  • ✅ The index.html script I added is running (I see the console log)
  • ✅ The appropriate base path is being picked up (/dev/ – I see it in the console log)
  • ✅ The base tag is being set correctly (I can see this by inspecting via the browser dev tools)
  • ❌ The URL being requested in the browser does not contain /dev/
    • Actual URL: cdn.com/script.js
    • Expected URL: cdn.com/dev/script.js

❓(Not Yet attempted) Do I have to modify this at deploy time?

Do I need my deployment script to physically modify index.html to use the correct href in the <base> tag? That would be surprising, but I suppose it's possible. Seems like this would definitely be an answer; just hoping it's not the answer.

Question

How do I, at runtime, modify the base path so that Angular will download resources from the correct URL, including the sub-path from the CDN endpoint? Am I able to do this at runtime, or do I need to set this programmatically in the HTML at deployment time?

like image 592
SeanKilleen Avatar asked Jul 03 '26 16:07

SeanKilleen


1 Answers

Can you set the base href to something relative?

ng build --base-href ./

This will load the files relative to where your index file is.

like image 191
Mathew Berg Avatar answered Jul 05 '26 06:07

Mathew Berg