Angular 模板上的 .NET Core 2.1 基本 href 标签



我正在最新版本的Core 2.1中包含的.NET Core 2.1 + Angular 5模板之上为我们的团队构建一个模板,我们将应用程序部署到虚拟文件夹中,例如/it/myapp或/aa/myotherapp

在 2.0 模板上,基本 href 属性将自动设置,我假设因为它是用剃刀构建的,如下所示:

<base href="~/" />

但是,对于2.1 模板来说并非如此,我假设这是因为模板实际上只使用静态文件和新应用程序。使用水疗((

关于如何自动填充基本 href 标签的任何想法?

谢谢

是的,我知道这是一个老问题,但我希望这对某人有更多帮助。答案是关于 Angular 6 和 .NET Core 2.1。建议:解释有点大(对不起(

在Core 2.1中,我们有一个典型的启动.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
spa.Options.DefaultPage = $"/index.html";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}

重要的部分是

spa.UseAngularCliServer(npmScript: "start");

这告诉 .NET 使用在 package.json 中定义的脚本

{
"name": "client-app",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --base-href=/ --serve-path=/", //<--this line
"build": "ng build",
...
},
....
}

看到我们有两个选择。 --base-href 和 --serve-path

当我们执行应用程序时,我们收到了一个索引.html例如

<!DOCTYPE html>
<html>
<head>
<title>Angular i18n example</title>
<base href="/"
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<app-root>Loading...</app-root>
<script type="text/javascript" src="runtime.js"></script>
<script type="text/javascript" src="polyfills.js"></script>
<script type="text/javascript" src="styles.js"></script>
<script type="text/javascript" src="vendor.js"></script>
<script type="text/javascript" src="main.js"></script>
</body>
</html>

我们可以更改基本 href 更改我们的 package.json。但是,如果不更改 --serve-path ,我们的应用程序将失败,因为我们正在根据基本 href 查找脚本。

这个想法是脚本不依赖于基本 href。我希望脚本的 src 处于绝对路径中。这就是脚本变成的样子

<script type="text/javascript" src="/<serve-path>/runtime.js"></script>
<script type="text/javascript" src="/<serve-path>/polyfills.js"></script>
<script type="text/javascript" src="/<serve-path>/styles.js"></script>
<script type="text/javascript" src="/<serve-path>/vendor.js"></script>
<script type="text/javascript" src="/<serve-path>/main.js"></script>

所以,如果我们在.html写一些类似

<head>
<title>Angular i18n example</title>
<script>
var str = document.location.href;
...
document.write('<base href="' + str+ '" />');
</script>
<!--we remove base href="/"
<base href="/"
-->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>

我们的脚本正在从正确的路径中查找,并且应用程序可以正常工作。 ¿如何更改添加脚本的方式?好吧,我们必须在两个文件中进行一些更改:

  • index-html-webpack-plugin.js from node_modules\@angular-devkit\build-angular\src\angular-cli-files\plugins

  • 浏览器.js 来自 node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\webpack-configs

首先参见index-html-webpack-plugin中的类IndexHtmlWebpackPlugin.js

class IndexHtmlWebpackPlugin {
constructor(options) {
this._options = Object.assign({ input: 'index.html', output: 'index.html', entrypoints: ['polyfills', 'main'], sri: false }, options);
}
apply(compiler) {
....
const scriptElements = treeAdapter.createDocumentFragment();
for (const script of scripts) {
const attrs = [
{ name: 'type', value: 'text/javascript' },
//change the line
//{ name: 'src', value: (this._options.deployUrl || '') + script },
//by 
{ name: 'src', value: (this._options.baseHref)+(this._options.deployUrl || '') + script },
];
if (this._options.sri) {
const content = compilation.assets[script].source();
attrs.push(...this._generateSriAttributes(content));
}
const element = treeAdapter.createElement('script', undefined, attrs);
treeAdapter.appendChild(scriptElements, element);
}

了解我们如何将 this._options.baseHref 添加到脚本中 好吧,实际上在构造函数中我们还没有baseHref,这是因为我们必须更改文件浏览器.js 在

plugins: extraPlugins.concat([
new index_html_webpack_plugin_1.IndexHtmlWebpackPlugin({
input: path.resolve(root, buildOptions.index),
output: path.basename(buildOptions.index),
baseHref: buildOptions.baseHref,
entrypoints: package_chunk_sort_1.generateEntryPoints(buildOptions),
deployUrl: buildOptions.deployUrl,
//we add this line
servePath: buildOptions.servePath,
sri: buildOptions.subresourceIntegrity,
}),
]),

再走一步。当我们在索引中使用javascript编写基本标签时.html,我们不希望angular-cli添加这个标签。为此,我们唯一必须更改的是注释索引-html-webpack-plugin中的行.js

// Adjust base href if specified
if (typeof this._options.baseHref == 'string') {
let baseElement;
for (const headChild of headElement.childNodes) {
if (headChild.tagName === 'base') {
baseElement = headChild;
}
}
const baseFragment = treeAdapter.createDocumentFragment();
if (!baseElement) {
baseElement = treeAdapter.createElement('base', undefined, [
{ name: 'href', value: this._options.baseHref },
]);
//coment the two lines below
//        treeAdapter.appendChild(baseFragment, baseElement);
//        indexSource.insert(headElement.__location.startTag.endOffset + 1, parse5.serialize(baseFragment, { treeAdapter }));
}

仅此而已!!

另外两点内联

当我们使用 javascript 创建基本标签时,我们需要一个基本标签。否则,如果我们刷新页面,我们的基本 href 会发生变化,如果我们是,例如在页面主页中,我们的 url 将像 http://www.dominio.com/<某事>/<某事>/家。我们希望基地继续<一些东西>/<一些东西>。看看剧本,就像你想要的那样,例如

<script>
var items = document.location.href.split('/');
while (items.length>4)
items.pop();
document.write('<base href="' + items.join('/') + '" />');
</script>

最后一点,如果使唯一有效的网址是服务器作为SPA。为此,我们修改了我们的启动.cs使只有有效的 url 是服务器。(否则,一些网址,如 http://www.dominio.com/patata/patata 为我们的SPA提供服务( 在应用之间添加。UseMvc 和应用程序。使用水疗中间件

app.UseMvc(routes =>
{
...
});
//Add this Middleware
app.Use(async (context, next) =>
{
string path = context.Request.Path.Value.Substring(1);
bool encontrado = path.EndsWith(".js") || path.EndsWith(".css") || path.EndsWith(".map") || path.StartsWith("sockjs");
if (!encontrado)
{
//make here the check for the pages
//"silly" e.g.
encontrado==(path=="es/adminitrator" || path=="it/administrator")
}
if (encontrado)
await next.Invoke();
else
{
context.Response.ContentType = "text/html";
await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "error404.html"));
}
app.UseSpa(spa=>
{
....
}
});

更新

使用 java 脚本添加选项卡库,这是一个非常丑陋的解决方法。更好地利用BASE_REF提供程序

import {Component, NgModule} from '@angular/core';
import {APP_BASE_HREF} from '@angular/common';
@NgModule({
providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
})
class AppModule {}

最新更新