.NET Core 2.1基于Angular模板的href标签 [英] .NET core 2.1 base href tag on Angular template

查看:54
本文介绍了.NET Core 2.1基于Angular模板的href标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm building a template for our team on top of the .NET Core 2.1 + Angular 5 template included in the latest release of core 2.1, we deploy applications into virtual folders, for example /it/myapp, or /aa/myotherapp

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

On the 2.0 template the base href property would be set automatically, I'm assuming because it was built with razor, like this:

<base href="~/" />

但是对于2.1模板而言并非如此,我认为这是因为该模板实际上仅在新应用中使用静态文件.UseSpa()

However this is not true for the 2.1 template, I'm assuming it's because the template actually only uses static files, with the new app.UseSpa()

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

Any ideas on how I could automatically populate the base href tag?

谢谢

推荐答案

是的,我知道这是一个古老的问题,但是我希望这对其他人有所帮助.答案是关于Angular 6和.NET Core 2.1的.建议:解释有点大(抱歉)

Yes, I know it's an old question, but I hope this help someone more. The answer is about Angular 6 and .NET Core 2.1. Advice: the explanation is a bit large (sorry)

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

In Core 2.1, we have a tipical Startup.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中定义的脚本

this tell to .NET that use the script defined in 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

See that we have two options. --base-href and --serve-path

当我们执行应用程序时,我们收到了一个index.html之类的

When we execute the application, we received an index.html like

<!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查找脚本.

We can change the base href change our package.json. But if not change the --serve-path according, our app fails because we are looking for the script according to the base href.

这个想法是脚本不依赖于基本href.我希望脚本的src在绝对路径中.这就是脚本,就像

The idea is that the scripts not depending for base href. I want that the src of scripts was in absolute path. That's the scripts becomes like

    <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中写一些类似的内容

So, if we write in our .html some like

<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>

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

Our scripts are looking for from the correct path and the application works. ¿How change the way to add the scripts? Well, we have to make a few changes in two files:

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

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

browser.js node_modules \ @ angular-devkit \ build-angular \ src \ angular-cli-files \ models \ webpack-configs

browser.js from node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\webpack-configs

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

See first the class IndexHtmlWebpackPlugin in index-html-webpack-plugin.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,这是因为我们必须更改文件browser.js 在

see how we add the this._options.baseHref to the scripts Well, really in constructor we haven't baseHref, it is for we must change the file browser.js in

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,
    }),
]),

又一步.当我们在index.html中使用javascript编写基本标签时,我们不希望angular-cli添加此标签.为此,我们唯一需要更改的就是注释index-html-webpack-plugin.js中的行

One more step. As we are writen the base tag using javascript in our index.html, we don't want that angular-cli add this tag. For this, the only thing that we must change is comment the lines in index-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更改,并且例如在页面首页中,则我们的网址将类似于http://www.dominio.com/<东西>/<东西>/home.我们希望基地将继续<东西>/<东西>.看一下脚本,然后按自己的意愿进行操作,例如

When we create the base tag using javascript we need ajust the base. Else, if we refresh the page, our base href change and, if we are, e.g in page home, our url will be like http:// www.dominio.com/< something>/< something>/home. We want that the base will go on < something>/< something>. take a look to the script and ajust like your want,e.g.

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

最后一点,如果使仅有效的URL作为SPA服务器.为此,我们修改了startup.cs,使只有有效的url是服务器. (否则,某些网址,例如 http://www.dominio.com/patata/patata 会投放我们的SPA) 在app.UseMvc和app.UseSpa之间添加中间件

The last point if make that only valid url are server as SPA. For that, we modified our startup.cs make that only valid url was server. (else, some url like http://www.dominio.com/patata/patata serve our SPA) Add between app.UseMvc and app.UseSpa a Middleware

   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提供程序

Use java script to add tab base it's a really ugly work-around. Better use BASE_REF Provider

import {Component, NgModule} from '@angular/core';
import {APP_BASE_HREF} from '@angular/common';

@NgModule({
  providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
})
class AppModule {}

这篇关于.NET Core 2.1基于Angular模板的href标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆