[英]Angular 2+ - Set base href dynamically
我們有一個企業應用程序,它為客戶端使用 Angular 2。 我們的每個客戶都有自己獨特的 url,例如: https://our.app.com/customer-one
和https://our.app.com/customer-two
。 目前我們可以使用document.location
動態設置<base href...>
。 所以用戶點擊https://our.app.com/customer-two
並且<base href...>
被設置為/customer-two
...完美!
問題是,如果用戶位於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>
...
不幸的是,我們還沒有想法。 任何幫助都會很棒。
這里的標記答案並沒有解決我的問題,可能是不同的角度版本。 我能夠在終端/外殼中使用以下angular cli
命令實現預期的結果:
ng build --base-href /myUrl/
ng build --bh /myUrl/
或ng build --prod --bh /myUrl/
這僅將構建版本中的<base href="/">
更改為<base href="/myUrl/">
,這非常適合我們在開發和生產之間更改環境。 最好的部分是沒有代碼庫需要使用這種方法進行更改。
index.html
基本 href 保留為: <base href="/">
然后使用 angular cli 運行ng build --bh ./
以使其成為相對路徑,或者將./
替換為您需要的任何內容。
正如上面的示例顯示了如何從命令行執行此操作,這里是如何將其添加到您的 angular.json 配置文件中。
這將用於為本地開發ng serving
"architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "baseHref": "/testurl/",
這是特定於配置構建的配置,例如 prod:
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"baseHref": "/testurl/",
官方angular-cli
文檔參考了用法。
這就是我們最終要做的事情。
將此添加到 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'] || '/' }
{ 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 { }
根據您 (@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;
}
在同一個域中構建多個應用程序時,我使用當前工作目錄./
:
<base href="./">
在旁注中,我使用.htaccess
來幫助我在頁面重新加載時路由:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.html [L]
@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 { }
如果您為 APP_BASE_HREF 不透明令牌提供值,則不必在 index.html 中指定基本標記。
這在生產環境中對我來說很好
<base href="/" id="baseHref">
<script>
(function() {
document.getElementById('baseHref').href = '/' + window.location.pathname.split('/')[1] + "/";
})();
</script>
在 angular4 中,您還可以在 .angular-cli.json 應用程序中配置 baseHref。
在 .angular-cli.json
{ ....
"apps": [
{
"name": "myapp1"
"baseHref" : "MY_APP_BASE_HREF_1"
},
{
"name": "myapp2"
"baseHref" : "MY_APP_BASE_HREF_2"
},
],
}
這會將 index.html 中的基本 href 更新為 MY_APP_BASE_HREF_1
ng build --app myapp1
如果您使用的是 Angular CLI 6,則可以使用 angular.json 中的 deployUrl/baseHref 選項(項目 > xxx > 架構師 > 構建 > 配置 > 生產)。 這樣,您可以輕松地為每個項目指定 baseUrl。
通過查看已構建應用程序的 index.html 來檢查您的設置是否正確。
有一個類似的問題,實際上我最終在我的網絡中探測了一些文件的存在。
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>
附加組件:如果您想要例如:/users 作為路由器的應用程序基礎,/public 作為資產使用的基礎
$ ng build -prod --base-href /users --deploy-url /public
您可以使用以下方法在 app.module.ts 文件中動態設置基本 href: https ://angular.io/api/common/APP_BASE_HREF
import {Component, NgModule} from '@angular/core';
import {APP_BASE_HREF} from '@angular/common';
@NgModule({
providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
})
class AppModule {}
在 package.json 中將標志 --base-href 設置為相對路徑:
"script": {
"build": "ng build --base-href ./"
}
我遲到了,但如果你要部署到 IIS,你可以使用重寫規則(我相信它也可以用其他網絡服務器來完成)。
您可以在請求 index.html 時修改傳出響應的內容並動態替換基本 href。 (url 重寫模塊必須安裝到 IIS 中)
以下示例假設您的 index.html 中有<base href="/angularapp/">
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<outboundRules>
<rule name="Modify base href to current path">
<match filterByTags="Base" pattern="^(.*)(/angularapp/)(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{REQUEST_URI}" pattern="^(.*)/index.html$"/>
</conditions>
<action type="Rewrite" value="{C:1}/" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
這一直是一個令人頭疼的問題,#location 策略似乎並沒有按照罐子上說的那樣做(似乎這是一個明顯的修復,但遺憾的是不是)所以這對我有用。 感謝大家指點!
請注意,我正在從我的應用程序中調用與應用程序路徑相關的 php 個頁面,這在刷新時出錯,因為文件夾級別太高。 這在下面配置的in2部分中得到解決。
創建一個 web.config 文件並將其放入您的 /src 文件夾中
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="in2" stopProcessing="true">
<match url="(.*)(.php)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="../{R:0}" />
</rule>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="../myappname/" />
</rule>
</rules>
</rewrite>
</system.webServer>
創建一個myappname.html文件,放到/src文件夾下,將兩者都添加到assets下的Angular.json build部分
"assets":{ ["projects/myapp/src/myappname.html","projects/toolbar2/src/web.config"
]
在 index.html
<script type='text/javascript'>
function configExists(url) {
var req = new XMLHttpRequest();
req.open('GET', url, false);
req.send();
return req.status==200;
}
var probePath = 'myappname.html';
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 : '/') + "' />");
坦率地說,你的案子對我來說很好!
我正在使用 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>
我只是改變了:
<base href="/">
對此:
<base href="/something.html/">
不要忘記以 / 結尾
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.