cdn.com/dev
, cdn.com/test
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.
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
)
APP_BASE_HREF
and use it as a providerI 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.
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 { }
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.base
href directly in HTMLIn 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>
/dev/
– I see it in the console log)/dev/
cdn.com/script.js
cdn.com/dev/script.js
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.
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?
As far as I have been able to determine, the only ways to modify the base href is:
angular.json file
-- but this would be applied at build time, and so wouldn't work for a build-once, deploy-many scenariong build --base-href="./dev"
-- but again, this is applied at build time, and wouldn't apply to all the deployed environments after that one build.<base>
tag within index.html
itself. But again, when deployed to multiple places, this won't meet my needs.So, as far as I am able to tell, the solution in this case for me will be to have the deployment script modify index.html
to ensure the base
tag within it aligns with the environment it's being deployed to.
I wrote a tiny PowerShell script that can be used during the deployment process, in case it's convenient for anyone else:
<#
.SYNOPSIS
Modifies an HTML file to set the base href with the appropriate CDN endpoint.
.EXAMPLE
# Can use relative path to file
.\TransformBaseHref.ps1 -PathToHtmlFile ..\code\webapp\dist\webapp\index.html -CDNPath "EnvironmentName"
.EXAMPLE
# Can use full path to file
.\TransformBaseHref.ps1 -PathToHtmlFile C:\path\to\index.html -CDNPath "EnvironmentName"
.EXAMPLE
# When index.html is in Current directory
.\TransformBaseHref.ps1 -PathToHtmlFile index.html -CDNPath "EnvironmentName"
#>
Param (
[Parameter(Mandatory = $true, HelpMessage = "The path to the html file to be updated.")]
[string] $PathToHtmlFile,
[Parameter(Mandatory = $true, HelpMessage = "The name of the CDN subfolder, e.g. 'develop' for the development environment")]
[string] $CDNPath
)
((Get-Content $PathToHtmlFile).Replace("<base href=""/"">", "<base href=""/$CDNPath/"">")) | Set-Content $PathToHtmlFile