Best Practices for Dynamic Base Href in Angular: `APP_BASE_HREF` to the Rescue!
In Angular applications, the base href (or base URL) specifies the root path where your application's assets (like JavaScript files, images, CSS) reside. By default, it's usually set to the root of your web application (/
). However, there are scenarios where you might need to adjust this base href dynamically at runtime.
Why Set the Base Href Dynamically?
Here are some common reasons you might want to do this:
- Multi-tenant Applications: If you're serving the same Angular application to multiple customers, each with their own subdomain or path (e.g.,
https://our.app.com/customer-one
andhttps://our.app.com/customer-two
), you'll need to adjust the base href to point to the correct location of assets for each customer. - Deployment Flexibility: If your application might be deployed to different environments (e.g., development, staging, production) with varying URLs, setting the base href dynamically allows for easier configuration.
Approaches to Dynamic Base Href in Angular 2+:
There are two primary methods to achieve this dynamic behavior:
-
Using the
APP_BASE_HREF
Token:- Angular provides a built-in token named
APP_BASE_HREF
. - In your
AppModule
, you can inject this token and provide a factory function that determines the base href based on your logic. - Here's an example:
import { NgModule, Inject } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { RouterModule } from '@angular/router'; import { APP_BASE_HREF } from '@angular/common'; @NgModule({ imports: [BrowserModule, RouterModule.forRoot([])], declarations: [AppComponent], bootstrap: [AppComponent], providers: [ { provide: APP_BASE_HREF, useFactory: () => { const host = window.location.host; if (host === 'www.domain.com:9083/portal') { return '/portal'; } else { return '/newapp'; } } } ] }) export class AppModule {}
In this example, the factory function checks the current host and sets the base href to either
/portal
or/newapp
accordingly. - Angular provides a built-in token named
-
Manual DOM Manipulation (Less Common):
Key Considerations:
- Ensure that your logic for determining the base href is accurate and consistent across different environments.
- When using the
APP_BASE_HREF
token approach, make sure to provide it in theproviders
array of yourAppModule
. - If you have complex base href requirements, consider using a service to manage the logic and provide a more centralized solution.
import { NgModule, Inject } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // Import for illustrative purposes
import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { APP_BASE_HREF } from '@angular/common';
@NgModule({
imports: [BrowserModule, FormsModule, RouterModule.forRoot([])], // Include FormsModule for completeness
declarations: [AppComponent],
bootstrap: [AppComponent],
providers: [
{
provide: APP_BASE_HREF,
useFactory: () => {
const host = window.location.host;
if (host === 'www.domain.com:9083/portal') {
return '/portal';
} else {
return '/newapp';
}
}
}
]
})
export class AppModule {}
Explanation:
- We import necessary modules like
BrowserModule
,FormsModule
(for illustration),RouterModule
, andAPP_BASE_HREF
from@angular/core
and@angular/common
. - In the
AppModule
, we define a factory function that checks the current host (window.location.host
) and returns the appropriate base href (/portal
or/newapp
). - We provide the factory function using
useFactory
for theAPP_BASE_HREF
token in theproviders
array.
This approach is generally not recommended, but here's an example for reference:
<!doctype html>
<html>
<head>
<title>My App</title>
<script>
window['base-href'] = window.location.pathname; // Set base href based on pathname
</script>
</head>
<body>
<app-root></app-root>
</body>
</html>
- We directly set the
base-href
property on thewindow
object using JavaScript in theindex.html
file. - This approach bypasses Angular's dependency injection, so it's less maintainable.
-
Using
APP_BASE_HREF
Token (Recommended): -
Environment Variables:
-
Server-Side Rendering (SSR) with Configuration:
Less Recommended Approaches:
- Manual DOM Manipulation: As mentioned earlier, directly manipulating the DOM in
index.html
with JavaScript is generally discouraged. It bypasses Angular's dependency injection and can lead to maintenance challenges. - Custom Providers (Rare): In very specific scenarios, you might create a custom service that manages the base href logic. However, this complexity is usually unnecessary unless you have a very intricate base href determination process.
Choosing the Right Approach:
The best method depends on your specific requirements and application architecture. Here's a general guideline:
- For most cases, using the
APP_BASE_HREF
token is the recommended approach. - If you need environment-specific base href values, consider environment variables during the build process.
- SSR with server-side configuration is a good choice if you're already using SSR for other benefits.
- Avoid manual DOM manipulation and custom providers unless absolutely necessary due to their downsides.
angular