Угловой 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>