We have an enterprise app that uses Angular 2 for the client. Each of our customers has their own unique url, ex: https://our.app.com/customer-one
and https://our.app.com/customer-two
. Currently we are able to set the <base href...>
dynamically using document.location
. So user hits https://our.app.com/customer-two
and <base href...>
gets set to /customer-two
...perfect!
The problem is if the user is for example at https://our.app.com/customer-two/another-page
and they refresh the page or try to hit that url directly, the <base href...>
gets set to /customer-two/another-page
and the resources can't be found.
We've tried the following to no avail:
<!doctype html>
<html>
<head>
<script type='text/javascript'>
var base = document.location.pathname.split('/')[1];
document.write('<base href="/' + base + '" />');
</script>
...
Unfortunately we are fresh out of ideas. Any help would be amazing.
This question is related to
angular
The marked answer here did not solve my issue, possibly different angular versions. I was able to achieve the desired outcome with the following angular cli
command in terminal / shell:
ng build --base-href /myUrl/
ng build --bh /myUrl/
or ng build --prod --bh /myUrl/
This changes the <base href="/">
to <base href="/myUrl/">
in the built version only which was perfect for our change in environment between development and production. The best part was no code base requires changing using this method.
index.html
base href as: <base href="/">
then run ng build --bh ./
with angular cli to make it a relative path, or replace the ./
with whatever you require.
As the example above shows how to do it from command line, here is how to add it to your angular.json configuration file.
This will be used for all ng serving
for local development
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"baseHref": "/testurl/",
This is the config specific for configuration builds such as prod:
"configurations": {
"Prod": {
"fileReplacements": [
{
"replace": src/environments/environment.ts",
"with": src/environments/environment.prod.ts"
}
],
"baseHref": "./productionurl/",
The official angular-cli
documentation referring to usage.
Based on your (@sharpmachine) answer, I was able to further refactor it a little, so that we don't have to hack out a function in index.html
.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { APP_BASE_HREF, Location } from '@angular/common';
import { AppComponent } from './';
import { getBaseLocation } from './shared/common-functions.util';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
HttpModule,
],
bootstrap: [AppComponent],
providers: [
appRoutingProviders,
{
provide: APP_BASE_HREF,
useFactory: getBaseLocation
},
]
})
export class AppModule { }
And, ./shared/common-functions.util.ts
contains:
export function getBaseLocation() {
let paths: string[] = location.pathname.split('/').splice(1, 1);
let basePath: string = (paths && paths[0]) || 'my-account'; // Default: my-account
return '/' + basePath;
}
I use the current working directory ./
when building several apps off the same domain:
<base href="./">
On a side note, I use .htaccess
to assist with my routing on page reload:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.html [L]
Simplification of the existing answer by @sharpmachine.
import { APP_BASE_HREF } from '@angular/common';
import { NgModule } from '@angular/core';
@NgModule({
providers: [
{
provide: APP_BASE_HREF,
useValue: '/' + (window.location.pathname.split('/')[1] || '')
}
]
})
export class AppModule { }
You do not have to specify a base tag in your index.html, if you are providing value for APP_BASE_HREF opaque token.
This work fine for me in prod environment
<base href="/" id="baseHref">
<script>
(function() {
document.getElementById('baseHref').href = '/' + window.location.pathname.split('/')[1] + "/";
})();
</script>
In angular4, you can also configure the baseHref in .angular-cli.json apps.
in .angular-cli.json
{ ....
"apps": [
{
"name": "myapp1"
"baseHref" : "MY_APP_BASE_HREF_1"
},
{
"name": "myapp2"
"baseHref" : "MY_APP_BASE_HREF_2"
},
],
}
this will update base href in index.html to MY_APP_BASE_HREF_1
ng build --app myapp1
If you are using Angular CLI 6, you can use the deployUrl/baseHref options in angular.json (projects > xxx > architect > build > configurations > production). In this way, you can easily specify the baseUrl per project.
Check that your settings are correct by looking at the index.html of the built app.
Add-ons:If you want for eg: /users as application base for router and /public as base for assets use
$ ng build -prod --base-href /users --deploy-url /public
Had a similar problem, actually I ended up in probing the existence of some file within my web.
probePath would be the relative URL to the file you want to check for (kind of a marker if you're now at the correct location), e.g. 'assets/images/thisImageAlwaysExists.png'
<script type='text/javascript'>
function configExists(url) {
var req = new XMLHttpRequest();
req.open('GET', url, false);
req.send();
return req.status==200;
}
var probePath = '...(some file that must exist)...';
var origin = document.location.origin;
var pathSegments = document.location.pathname.split('/');
var basePath = '/'
var configFound = false;
for (var i = 0; i < pathSegments.length; i++) {
var segment = pathSegments[i];
if (segment.length > 0) {
basePath = basePath + segment + '/';
}
var fullPath = origin + basePath + probePath;
configFound = configExists(fullPath);
if (configFound) {
break;
}
}
document.write("<base href='" + (configFound ? basePath : '/') + "' />");
</script>
In package.json set flag --base-href to relative path:
"script": {
"build": "ng build --base-href ./"
}
Frankly speaking, your case works fine for me!
I'm using Angular 5.
<script type='text/javascript'>
var base = window.location.href.substring(0, window.location.href.toLowerCase().indexOf('index.aspx'))
document.write('<base href="' + base + '" />');
</script>
I just changed:
<base href="/">
to this:
<base href="/something.html/">
don't forget ending with /
Source: Stackoverflow.com