web-dev-qa-db-ja.com

ASP.NET Core 2.1 Angular 6.0 SPAテンプレート-静的ページではなくインデックス用のかみそりページ(cshtml)

webpack設定の_ASP.NET Core 2.0 Angular 5_アプリケーションを_ASP.NET Core 2.1 Angular 6_の_Angular-Cli_に移行しようとしています。

短い質問:

_Microsoft.AspNetCore.SpaServices.Extensions_を使用してcshtmlからかみそりページのディレクティブを強制的に解析するにはどうすればよいですか?

_index.html_の_Angular.json_を使用したくありませんが、_index.cshtml_は使用しません。

長い説明:

Angular template から新しいASP.NET Coreプロジェクトを開始しました。魔法のように機能するものがかなりあります。

  1. _index.html_フォルダー内には、アプリケーションの起動時に自動的に提供される_ClientApp/src_ファイルがあります。
  2. アプリケーションの実行時に、_</body>_の_index.html_タグの前に(最初のポイントから)いくつかのスクリプトが挿入されます:_inline.bundle.js_、_polyfills.bundle.js_、_vendor.bundle.js_、_main.bundle.js_および_styles.bundle.css_タグの前の_</head>_。

これらのスクリプトを誰が挿入したかはわかりませんが、Razorページ(cshtml)に挿入したいです。

古いプロジェクトのコードを使用しようとしました:

_<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>@ViewData["Title"]</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
@{string googleAnalyticsId = Html.Raw(ViewData["GoogleAnalyticsId"]).ToString();}
@if (!string.IsNullOrEmpty(googleAnalyticsId))
{
    <script>
        (function(i, s, o, g, r, a, m)
        {
           ...
        })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');

        ga('create', '@googleAnalyticsId', 'auto');
    </script>
}
<script>
    @Html.Raw(ViewData["TransferData"])
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/0.8.2/css/flag-icon.min.css" async defer />
<script src="https://apis.google.com/js/platform.js" async defer></script>
<app>
    <!-- loading layout replaced by app after startupp -->
    <div class="page-loading">
        <div class="bar">
            <i class="sphere"></i>
        </div>
    </div>
</app>
</body>
</html>
_

_Angular.json_のインデックスオプションをこの_index.cshtml_にポイントします。

_  "architect": {
    "build": {
      "builder": "@angular-devkit/build-angular:browser",
        "options": {
            "outputPath": "wwwroot/dist",
            "index": "Views/Home/Index.cshtml",   //<----- here
_

問題は、コンテンツ(すべての@タグ)がASP.NET Coreによって処理されないが、直接コンテンツを出力することです:

_<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>@ViewData["Title"]</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
@{string googleAnalyticsId = Html.Raw(ViewData["GoogleAnalyticsId"]).ToString();}
@if (!string.IsNullOrEmpty(googleAnalyticsId))
{
    <script>
...
_

ただし、次のようにする必要があります。

_<!DOCTYPE html>
<html>
<head>
    <base href="/" />
    <title>Test title</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
    <script>
_

いくつかの変数(appsettings.jsonから)をhtmlページの最後に出力したい。私はすでにASP.NET Coreを使用しているので、Razorページは良い解決策のようです。

私も試してみます:
新しいRazorPageを追加するには、C#コンテンツ(@ディレクティブ)が処理されますが、誰もAngularスクリプトを挿入していません。

AndyCunninghamの回答に対する回答:

_ng build --prod_は次のファイルを書き込みます。

_<script type="text/javascript" src="runtime.b38c91f828237d6db7f0.js"></script><script type="text/javascript" src="polyfills.2fc3e5708eb8f0eafa68.js"></script><script type="text/javascript" src="main.16911708c355ee56ac06.js"></script> 
_

_index.html_に。かみそりのページにこれを書く方法。

11
Makla

それは古い質問ですが、答えが誰かを助けることを願っています

まあ、difficutはwebpackがindex.cshtmlにscriptsタグを挿入するようにしていますが、index.cshtmlにタグを含めることができます

@{
    ViewData["title"] = "I'am from cshtml";
}
<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>

その後、あなたのようなMVCをルータすることができます

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");

    routes.MapRoute(
        name: "spa-fallback",
        template: "{*url:regex(^((?!.css|.map|.js|sockjs).)*$)}",
        defaults: new { controller = "Home", action = "Index" });

});

{controller} {action = Index}/{id?}に対応しないすべてのルートが「spa-fallback」に分類され、ファイルに.cssまたは.mapまたは.jsまたは.sockjsが含まれていない場合、ホーム/インデックス。 .NETの「正規表現」がスクリプトファイルを提供することが必要です。

最後のステップは、outputHashing:allを使用してスクリプトの名前を維持するように、angular.jsonを構成します

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "ClientApp": {
      ...
      "architect": {
        "build": {
            ...
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all", //<--add this line
                  ...
            },
            ....
  },
  "defaultProject": "ClientApp"
}

最後に、startup.csで使用できるURLが有効かどうか(他のURLサーバーのインデックスページ)を確認できます。

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)
    {
        ..use your code to check the url...
    }
    if (encontrado)
        await next.Invoke(); //<--continue
    else
    {   //send to an error404 page
        context.Response.ContentType = "text/html";
        await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "error404.html"));
    }
});

注:スクリプトのhrefを絶対パスに配置します(例:src = "/ runtime.js")。パッケージjsonには、次のようないくつかのスクリプトを含めることができます。

"scripts": {
    "ng": "ng",
    "start": "ng serve --base-href=/ --serve-path=/",
    "start:fr": "ng serve --base-href=/fr-FR/ --configuration=fr --serve-path=/fr-FR",
    "build": "ng build",
    ...
  },

--serve-path = fr-FRを使用する場合、スクリプトのhrefはこのserve-pathを使用する必要があります。 src = "/ fr-FR/runtime.js"

4
Eliseo

私はこの答えをReact SPA拡張機能での経験に基づいていますが、Angular、同様に 同じ_ClientApp/index.html_ミドルウェアメカニズム 、および同じ _IApplicationBuilder.UseSpa_ エントリポイント。

問題は、app.UseSpa(...)を使用すると、この拡張機能のデフォルト実装 が構成することですaすべてのUI要求をリッスンし、それらをindex.html に転送するミドルウェア。

プロジェクトでこれを回避する方法の簡単な例を作成しました: https://github.com/andycmaj/aspnet_spa_without_indexhtml/pull/1/files index.htmlを無視し、代わりにカミソリビューを使用するために何を変更する必要があるかを示します。

基本的に、UseSpaが行うことを再実装しましたが、インターセプトや障害のあるミドルウェアをindex.htmlにアタッチしませんでした。

Home剃刀ビューは、index.htmlが行っていたより重要なことを行う必要があることに注意してください。最も重要なことは、SPA静的コンテンツミドルウェアによって提供される _bundle.js_ を含める必要があることです。

4
AndyCunningham