Угловой 2/4/5 - Устанавливает базовый href динамически
У нас есть корпоративное приложение, которое использует Angular 2 для клиента. Каждый из наших клиентов имеет свой собственный уникальный URL, например: https://our.app.com/customer-one
и https://our.app.com/customer-two
. В настоящее время мы можем динамически установить <base href...>
, используя document.location
. Таким образом, пользовательские тэги https://our.app.com/customer-two
и <base href...>
устанавливаются на /customer-two
... perfect!
Проблема заключается в том, что пользователь, например, находится в https://our.app.com/customer-two/another-page
, и он обновляет страницу или пытается напрямую нажать на этот URL-адрес, <base href...>
получает значение /customer-two/another-page
и ресурсы не могут быть найдены.
Мы пробовали следующее безрезультатно:
<!doctype html>
<html>
<head>
<script type='text/javascript'>
var base = document.location.pathname.split('/')[1];
document.write('<base href="/' + base + '" />');
</script>
...
К сожалению, мы свежим от идей. Любая помощь будет потрясающей.
Ответы
Ответ 1
Вот что мы в итоге сделали.
Добавьте это в index.html. Это должно быть первым в разделе <head>
<base href="/">
<script>
(function() {
window['_app_base'] = '/' + window.location.pathname.split('/')[1];
})();
</script>
Затем в файле app.module.ts
добавьте { provide: APP_BASE_HREF, useValue: window['_app_base'] || '/' }
в список поставщиков, например:
import { NgModule, enableProdMode, provide } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { APP_BASE_HREF, Location } from '@angular/common';
import { AppComponent, routing, appRoutingProviders, environment } from './';
if (environment.production) {
enableProdMode();
}
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
HttpModule,
routing],
bootstrap: [AppComponent],
providers: [
appRoutingProviders,
{ provide: APP_BASE_HREF, useValue: window['_app_base'] || '/' },
]
})
export class AppModule { }
Ответ 2
Отмеченный ответ здесь не решил мою проблему, возможно, различные угловые версии. Мне удалось добиться желаемого результата с помощью следующей angular cli
команды angular cli
в терминале/оболочке:
ng build --base-href/myUrl/
ng build --bh/myUrl/
или ng build --prod --bh/myUrl/
Это изменяет <base href="/">
на <base href="/myUrl/">
в встроенной версии, что идеально подходит для нашего изменения среды между разработкой и производством. Самое приятное, что кодовая база не требует изменений с помощью этого метода.
Подводя итог, оставьте ваш index.html
base href как: <base href="/">
затем запустите ng build --bh./
с угловым cli, чтобы сделать его относительным путем, или замените ./
что вам нужно.
Обновить:
Как показано в примере выше, как это сделать из командной строки, вот как добавить его в файл конфигурации angular.json.
Это будет использоваться для всех ng serving
для локального развития
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"baseHref": "/testurl/",
Это конфигурация, специфичная для конфигурационных сборок, таких как prod:
"configurations": {
"Prod": {
"fileReplacements": [
{
"replace": src/environments/environment.ts",
"with": src/environments/environment.prod.ts"
}
],
"baseHref": "./productionurl/",
Официальная angular-cli
документация, ссылающаяся на использование.
Ответ 3
Основываясь на вашем ответе (@sharpmachine), я смог еще немного его реорганизовать, так что нам не нужно взламывать функцию в 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 { }
И ./shared/common-functions.util.ts
содержит:
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;
}
Ответ 4
Я использую текущий рабочий каталог ./
при создании нескольких приложений из одного домена:
<base href="./">
На боковой ноте я использую .htaccess
, чтобы помочь с моей маршрутизацией на перезагрузке страницы:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.html [L]
Ответ 5
Упрощение существующего ответа @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 { }
Вам не нужно указывать базовый тег в вашем index.html, если вы предоставляете значение для непрозрачного токена APP_BASE_HREF.
Ответ 6
В угловом4 вы также можете настроить baseHref в приложениях .angular-cli.json.
в .angular-cli.json
{ ....
"apps": [
{
"name": "myapp1"
"baseHref" : "MY_APP_BASE_HREF_1"
},
{
"name": "myapp2"
"baseHref" : "MY_APP_BASE_HREF_2"
},
],
}
это обновит base href в index.html до MY_APP_BASE_HREF_1
ng build --app myapp1
Ответ 7
Эта работа отлично подходит для меня в среде prod
<base href="/" id="baseHref">
<script>
(function() {
document.getElementById('baseHref').href = '/' + window.location.pathname.split('/')[1] + "/";
})();
</script>
Ответ 8
Если вы используете Angular CLI 6, вы можете использовать опции deployUrl/baseHref в проектах angular.json (проекты> xxx> architect> build> configuration>). Таким образом, вы можете легко указать baseUrl для каждого проекта.
Проверьте правильность настроек, посмотрев на index.html встроенного приложения.
Ответ 9
Дополнения: Если вы хотите, например, для: /users в качестве базы приложения для маршрутизатора и /public в качестве базы для использования ресурсов
$ ng build -prod --base-href /users --deploy-url /public
Ответ 10
Откровенно говоря, ваше дело прекрасно работает для меня!
Я использую 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>
Ответ 11
У меня была похожая проблема, на самом деле я обнаружил, что в моей сети есть какой-то файл.
probePath - это относительный URL-адрес файла, который вы хотите проверить (вид маркера, если вы сейчас находитесь в правильном месте), например, 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>