JavaScript サービスを使用して ASP.NET Core でのシングル ページ アプリケーションを作成するにはUse JavaScript Services to Create Single Page Applications in ASP.NET Core

によってScott AddieFiyaz HasanBy Scott Addie and Fiyaz Hasan

シングル ページ アプリケーション (SPA) は、その固有の機能豊富なユーザー エクスペリエンスのための web アプリケーションの人気のある型です。A Single Page Application (SPA) is a popular type of web application due to its inherent rich user experience. クライアント側 SPA フレームワークやライブラリの統合などAngularまたはReact、ASP.NET Core などのサーバー側のフレームワークでを困難にすることができます。Integrating client-side SPA frameworks or libraries, such as Angular or React, with server-side frameworks such as ASP.NET Core can be difficult. JavaScript のサービスは、統合プロセスの手間を削減する開発されました。JavaScript Services was developed to reduce friction in the integration process. これにより、別のクライアントおよびサーバー テクノロジ スタックとの間のシームレスな操作ができます。It enables seamless operation between the different client and server technology stacks.

JavaScript のサービスとはWhat is JavaScript Services

JavaScript のサービスは、ASP.NET Core 用のクライアント側のテクノロジのコレクションです。JavaScript Services is a collection of client-side technologies for ASP.NET Core. その目的は、Spa を構築するための開発者の推奨されるサーバー側プラットフォームとしての ASP.NET Core の位置です。Its goal is to position ASP.NET Core as developers' preferred server-side platform for building SPAs.

JavaScript のサービスは、2 つの個別の NuGet パッケージで構成されます。JavaScript Services consists of two distinct NuGet packages:

これらのパッケージには、次のシナリオがあります。These packages are useful in the following scenarios:

  • サーバーでの JavaScript を実行します。Run JavaScript on the server
  • SPA フレームワークやライブラリを使用します。Use a SPA framework or library
  • Webpack とクライアント側アセットをビルドします。Build client-side assets with Webpack

SpaServices パッケージを使用してこの記事内のフォーカスの多くは配置されます。Much of the focus in this article is placed on using the SpaServices package.

SpaServices とはWhat is SpaServices

SpaServices は、Spa を構築するための開発者の推奨されるサーバー側プラットフォームとしての ASP.NET Core の位置に作成されました。SpaServices was created to position ASP.NET Core as developers' preferred server-side platform for building SPAs. SpaServices は ASP.NET core で Spa を開発する必要はありませんし、開発者は特定のクライアント フレームワークにロックがされません。SpaServices isn't required to develop SPAs with ASP.NET Core, and it doesn't lock developers into a particular client framework.

SpaServices は、次のような便利なインフラストラクチャを提供します。SpaServices provides useful infrastructure such as:

総称して、これらのインフラストラクチャ コンポーネントは、開発ワークフローと、実行時のエクスペリエンスの両方を強化します。Collectively, these infrastructure components enhance both the development workflow and the runtime experience. コンポーネントを個別に採用することができます。The components can be adopted individually.

SpaServices を使用するための前提条件Prerequisites for using SpaServices

SpaServices を使用するには、次のようにインストールします。To work with SpaServices, install the following:

  • Node.js (バージョン 6 以降) で npmNode.js (version 6 or later) with npm

    • これらのコンポーネントがインストールされを検出できることを確認するには、コマンドラインから、次を実行します。To verify these components are installed and can be found, run the following from the command line:

      node -v && npm -v
      
    • 操作は必要ない場合は、Azure の web サイトに展開する、—Node.js がインストールされ、サーバー環境で使用できます。If deploying to an Azure web site, no action is required—Node.js is installed and available in the server environments.

  • .NET Core SDK 2.0 以降.NET Core SDK 2.0 or later

    • 選択して Windows の Visual Studio 2017 を使用して、SDK がインストールされている、 .NET Core クロス プラットフォーム開発ワークロード。On Windows using Visual Studio 2017, the SDK is installed by selecting the .NET Core cross-platform development workload.
  • Microsoft.AspNetCore.SpaServices NuGet パッケージMicrosoft.AspNetCore.SpaServices NuGet package

サーバー側の事前Server-side prerendering

ユニバーサル (isomorphic とも呼ばれます) のアプリケーションは、サーバーとクライアントの両方で実行できる JavaScript アプリケーションです。A universal (also known as isomorphic) application is a JavaScript application capable of running both on the server and the client. Angular、React、およびその他の一般的なフレームワークは、このアプリケーションの開発スタイルのユニバーサル プラットフォームを提供します。Angular, React, and other popular frameworks provide a universal platform for this application development style. 考え方は、まず、Node.js を使用して、サーバー上のフレームワーク コンポーネントをレンダリングし、さらに、クライアントを実行しを委任します。The idea is to first render the framework components on the server via Node.js, and then delegate further execution to the client.

ASP.NET Coreタグ ヘルパーによって提供される SpaServices、サーバー上の JavaScript 関数を呼び出すことによってサーバー側の事前の実装を簡略化します。ASP.NET Core Tag Helpers provided by SpaServices simplify the implementation of server-side prerendering by invoking the JavaScript functions on the server.

サーバー側プリレンダ リングの前提条件Server-side prerendering prerequisites

インストール、 aspnet 事前npm パッケージ。Install the aspnet-prerendering npm package:

npm i -S aspnet-prerendering

サーバー側プリレンダ リング構成Server-side prerendering configuration

タグ ヘルパーは、プロジェクトの名前空間の登録を使用して探索可能にされて _ViewImports.cshtmlファイル。The Tag Helpers are made discoverable via namespace registration in the project's _ViewImports.cshtml file:

@using SpaServicesSampleApp
@addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
@addTagHelper "*, Microsoft.AspNetCore.SpaServices"

これらのタグ ヘルパーは Razor ビュー内の HTML のような構文を活用することで、低レベルの Api と直接通信の複雑さで抽象化します。These Tag Helpers abstract away the intricacies of communicating directly with low-level APIs by leveraging an HTML-like syntax inside the Razor view:

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

prerender モジュールの asp タグ ヘルパーasp-prerender-module Tag Helper

asp-prerender-moduleタグ ヘルパーの前のコード例で使用される実行ClientApp/dist/main-server.js Node.js を使用してサーバーにします。The asp-prerender-module Tag Helper, used in the preceding code example, executes ClientApp/dist/main-server.js on the server via Node.js. わかりやすくするためのために、 main server.jsファイルは、TypeScript、JavaScript にトランス パイルもタスクの成果物、 Webpackプロセスを構築します。For clarity's sake, main-server.js file is an artifact of the TypeScript-to-JavaScript transpilation task in the Webpack build process. Webpack のエントリ ポイントのエイリアスを定義しますmain-server; と、このエイリアスの依存関係グラフのトラバーサルが始まり、 ClientApp/ブート-server.tsファイル。Webpack defines an entry point alias of main-server; and, traversal of the dependency graph for this alias begins at the ClientApp/boot-server.ts file:

entry: { 'main-server': './ClientApp/boot-server.ts' },

次の Angular の例では、 ClientApp/ブート-server.tsファイルを利用、createServerRenderer関数とRenderResultの入力、 aspnet-prerendering npm パッケージを Node.js を使用してサーバー レンダリングを構成します。In the following Angular example, the ClientApp/boot-server.ts file utilizes the createServerRenderer function and RenderResult type of the aspnet-prerendering npm package to configure server rendering via Node.js. サーバー側のレンダリングが厳密に型指定された JavaScript にラップされて解決関数の呼び出しに渡される宛ての HTML マークアップPromiseオブジェクト。The HTML markup destined for server-side rendering is passed to a resolve function call, which is wrapped in a strongly-typed JavaScript Promise object. Promiseオブジェクトの重要性は、DOM のプレース ホルダー要素の挿入のページに HTML マークアップを非同期的に提供します。The Promise object's significance is that it asynchronously supplies the HTML markup to the page for injection in the DOM's placeholder element.

import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {
    const providers = [
        { provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
        { provide: 'ORIGIN_URL', useValue: params.origin }
    ];

    return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
        const appRef = moduleRef.injector.get(ApplicationRef);
        const state = moduleRef.injector.get(PlatformState);
        const zone = moduleRef.injector.get(NgZone);
        
        return new Promise<RenderResult>((resolve, reject) => {
            zone.onError.subscribe(errorInfo => reject(errorInfo));
            appRef.isStable.first(isStable => isStable).subscribe(() => {
                // Because 'onStable' fires before 'onError', we have to delay slightly before
                // completing the request in case there's an error to report
                setImmediate(() => {
                    resolve({
                        html: state.renderToString()
                    });
                    moduleRef.destroy();
                });
            });
        });
    });
});

asp の prerender データ タグ ヘルパーasp-prerender-data Tag Helper

組み合わせると、asp-prerender-moduleタグ ヘルパーのasp-prerender-dataタグ ヘルパーは、Razor ビューからサーバー側 JavaScript にコンテキスト情報を渡すために使用できます。When coupled with the asp-prerender-module Tag Helper, the asp-prerender-data Tag Helper can be used to pass contextual information from the Razor view to the server-side JavaScript. たとえば、次のマークアップは合格ユーザー データをmain-serverモジュール。For example, the following markup passes user data to the main-server module:

<app asp-prerender-module="ClientApp/dist/main-server"
        asp-prerender-data='new {
            UserName = "John Doe"
        }'>Loading...</app>

受信したUserName引数の組み込みの JSON シリアライザーを使用してシリアル化し、は、params.dataオブジェクト。The received UserName argument is serialized using the built-in JSON serializer and is stored in the params.data object. 次の例で Angular 内でパーソナライズされたあいさつ文を構築するデータの使用、h1要素。In the following Angular example, the data is used to construct a personalized greeting within an h1 element:

import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {
    const providers = [
        { provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
        { provide: 'ORIGIN_URL', useValue: params.origin }
    ];

    return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
        const appRef = moduleRef.injector.get(ApplicationRef);
        const state = moduleRef.injector.get(PlatformState);
        const zone = moduleRef.injector.get(NgZone);
        
        return new Promise<RenderResult>((resolve, reject) => {
            const result = `<h1>Hello, ${params.data.userName}</h1>`;

            zone.onError.subscribe(errorInfo => reject(errorInfo));
            appRef.isStable.first(isStable => isStable).subscribe(() => {
                // Because 'onStable' fires before 'onError', we have to delay slightly before
                // completing the request in case there's an error to report
                setImmediate(() => {
                    resolve({
                        html: result
                    });
                    moduleRef.destroy();
                });
            });
        });
    });
});

タグ ヘルパーで渡されたプロパティの名前を付けて表されますPascalCase表記します。Property names passed in Tag Helpers are represented with PascalCase notation. 同じプロパティ名で表現は JavaScript とは異なりcamelCaseします。Contrast that to JavaScript, where the same property names are represented with camelCase. 既定の JSON シリアル化の構成では、この違いを担当します。The default JSON serialization configuration is responsible for this difference.

展開すると、上記のコード例に、データ渡し可能サーバーからビューに hydrating、globalsプロパティに提供される、resolve関数。To expand upon the preceding code example, data can be passed from the server to the view by hydrating the globals property provided to the resolve function:

import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

export default createServerRenderer(params => {
    const providers = [
        { provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
        { provide: 'ORIGIN_URL', useValue: params.origin }
    ];

    return platformDynamicServer(providers).bootstrapModule(AppModule).then(moduleRef => {
        const appRef = moduleRef.injector.get(ApplicationRef);
        const state = moduleRef.injector.get(PlatformState);
        const zone = moduleRef.injector.get(NgZone);
        
        return new Promise<RenderResult>((resolve, reject) => {
            const result = `<h1>Hello, ${params.data.userName}</h1>`;

            zone.onError.subscribe(errorInfo => reject(errorInfo));
            appRef.isStable.first(isStable => isStable).subscribe(() => {
                // Because 'onStable' fires before 'onError', we have to delay slightly before
                // completing the request in case there's an error to report
                setImmediate(() => {
                    resolve({
                        html: result,
                        globals: {
                            postList: [
                                'Introduction to ASP.NET Core',
                                'Making apps with Angular and ASP.NET Core'
                            ]
                        }
                    });
                    moduleRef.destroy();
                });
            });
        });
    });
});

postList配列内で定義されている、globalsオブジェクトはグローバルで、ブラウザーにアタッチされてwindowオブジェクト。The postList array defined inside the globals object is attached to the browser's global window object. グローバル スコープにこの変数のホイストでは、特に、サーバーで 1 回と、クライアントでは、同じデータの読み込みに関連している、作業の重複がなくなります。This variable hoisting to global scope eliminates duplication of effort, particularly as it pertains to loading the same data once on the server and again on the client.

ウィンドウ オブジェクトにアタッチされているグローバルの postList 変数

Webpack 開発ミドルウェアWebpack Dev Middleware

Webpack 開発ミドルウェアWebpack がオンデマンドでリソースをビルドするための合理的な開発ワークフローが導入されています。Webpack Dev Middleware introduces a streamlined development workflow whereby Webpack builds resources on demand. ミドルウェアが自動的にコンパイルし、ページがブラウザーに再読み込みする際、クライアント側のリソースの機能します。The middleware automatically compiles and serves client-side resources when a page is reloaded in the browser. 別の方法では、サードパーティの依存関係またはカスタム コードが変更されたときに、プロジェクトの npm ビルド スクリプトを使用して Webpack を手動で起動します。The alternate approach is to manually invoke Webpack via the project's npm build script when a third-party dependency or the custom code changes. Npm スクリプトを作成する、 package.jsonファイルは、次の例に示します。An npm build script in the package.json file is shown in the following example:

"build": "npm run build:vendor && npm run build:custom",

Webpack 開発ミドルウェアの前提条件Webpack Dev Middleware prerequisites

インストール、 aspnet webpack npm パッケージ。Install the aspnet-webpack npm package:

npm i -D aspnet-webpack

Webpack 開発ミドルウェアの構成Webpack Dev Middleware configuration

次のコードを使用して HTTP 要求パイプラインに Webpack 開発ミドルウェアが登録されている、 Startup.csファイルのConfigureメソッド。Webpack Dev Middleware is registered into the HTTP request pipeline via the following code in the Startup.cs file's Configure method:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseWebpackDevMiddleware();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

// Call UseWebpackDevMiddleware before UseStaticFiles
app.UseStaticFiles();

UseWebpackDevMiddlewareする前に、拡張メソッドを呼び出す必要があります静的ファイルをホストしている登録を使用して、UseStaticFiles拡張メソッド。The UseWebpackDevMiddleware extension method must be called before registering static file hosting via the UseStaticFiles extension method. セキュリティ上の理由から、アプリは開発モードで実行時にのみ、ミドルウェアを登録します。For security reasons, register the middleware only when the app runs in development mode.

Webpack.config.jsファイルのoutput.publicPathプロパティに通知を監視するミドルウェア、distフォルダーの変更。The webpack.config.js file's output.publicPath property tells the middleware to watch the dist folder for changes:

module.exports = (env) => {
        output: {
            filename: '[name].js',
            publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
        },

ホットなモジュールの交換Hot Module Replacement

Webpack の考えるホット モジュールの交換(HMR) 機能の進化したものとしてWebpack 開発ミドルウェアします。Think of Webpack's Hot Module Replacement (HMR) feature as an evolution of Webpack Dev Middleware. すべて同じメリットが導入されて HMR が自動的に変更をコンパイルした後、ページのコンテンツを更新することでさらに、開発ワークフローを効率化します。HMR introduces all the same benefits, but it further streamlines the development workflow by automatically updating page content after compiling the changes. メモリ内の現在の状態と、SPA のデバッグ セッションに支障をきたすのブラウザーの更新でこれを混同しないでください。Don't confuse this with a refresh of the browser, which would interfere with the current in-memory state and debugging session of the SPA. Webpack 開発ミドルウェア サービスと、ブラウザーに変更がプッシュされることを意味すると、ブラウザーの間のライブ リンクがあります。There's a live link between the Webpack Dev Middleware service and the browser, which means changes are pushed to the browser.

ホットなモジュールの交換の前提条件Hot Module Replacement prerequisites

インストール、 webpack ホット ミドルウェアnpm パッケージ。Install the webpack-hot-middleware npm package:

npm i -D webpack-hot-middleware

ホットなモジュールの交換の構成Hot Module Replacement configuration

MVC の HTTP 要求パイプラインに HMR コンポーネントを登録する必要があります、Configureメソッド。The HMR component must be registered into MVC's HTTP request pipeline in the Configure method:

app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
    HotModuleReplacement = true
});

そうであったとしてWebpack 開発ミドルウェアUseWebpackDevMiddlewareする前に、拡張メソッドを呼び出す必要があります、UseStaticFiles拡張メソッド。As was true with Webpack Dev Middleware, the UseWebpackDevMiddleware extension method must be called before the UseStaticFiles extension method. セキュリティ上の理由から、アプリは開発モードで実行時にのみ、ミドルウェアを登録します。For security reasons, register the middleware only when the app runs in development mode.

Webpack.config.jsファイルを定義する必要があります、plugins場合でも、それを空の配列。The webpack.config.js file must define a plugins array, even if it's left empty:

module.exports = (env) => {
        plugins: [new CheckerPlugin()]

ブラウザーでアプリを読み込んだ後は、開発者ツールのコンソール タブは、HMR アクティブ化の確認を提供します。After loading the app in the browser, the developer tools' Console tab provides confirmation of HMR activation:

ホットのモジュールの交換接続メッセージ

ルーティングのヘルパーRouting helpers

ほとんどの ASP.NET Core ベースの Spa でクライアント側のルーティングが多くの場合、必要なサーバー側でルーティングだけでなく。In most ASP.NET Core-based SPAs, client-side routing is often desired in addition to server-side routing. SPA と MVC ルーティング システムは、競合することがなく個別に作業できます。The SPA and MVC routing systems can work independently without interference. ただし、課題を 1 つエッジ ケース読んだり: 404 の HTTP 応答を識別します。There's, however, one edge case posing challenges: identifying 404 HTTP responses.

シナリオの場合を検討してください、拡張子のないルートの/some/page使用されます。Consider the scenario in which an extensionless route of /some/page is used. 要求がパターン一致、サーバー側ルートがそのパターンのクライアント側ルートが一致するものとします。Assume the request doesn't pattern-match a server-side route, but its pattern does match a client-side route. ここでの受信要求を考えてみます/images/user-512.png、一般に、サーバー上の画像ファイルを検索する要求。Now consider an incoming request for /images/user-512.png, which generally expects to find an image file on the server. 任意のサーバー側のルートまたは静的ファイルにその要求されたリソースのパスが一致しない場合は、クライアント側アプリケーションは処理は、可能性がいない—一般に HTTP ステータス コード 404 を返すことが必要な。If that requested resource path doesn't match any server-side route or static file, it's unlikely that the client-side application would handle it—generally returning a 404 HTTP status code is desired.

ヘルパーのルーティングの前提条件Routing helpers prerequisites

クライアント側のルーティングの npm パッケージをインストールします。Install the client-side routing npm package. Angular を使用して、例として。Using Angular as an example:

npm i -S @angular/router

ヘルパーのルーティングの構成Routing helpers configuration

という名前の拡張メソッドMapSpaFallbackRouteで使用されて、Configureメソッド。An extension method named MapSpaFallbackRoute is used in the Configure method:

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

    routes.MapSpaFallbackRoute(
        name: "spa-fallback",
        defaults: new { controller = "Home", action = "Index" });
});

ルートは、構成されている順序で評価されます。Routes are evaluated in the order in which they're configured. その結果、defaultパターン一致の前のコード例ではルートが最初に使用します。Consequently, the default route in the preceding code example is used first for pattern matching.

新しいプロジェクトを作成するCreate a new project

JavaScript のサービスでは、事前構成済みのアプリケーション テンプレートを提供します。JavaScript Services provide pre-configured application templates. SpaServices は、さまざまなフレームワークおよびライブラリと、Angular、React、Redux などと連携してこれらのテンプレートで使用されます。SpaServices is used in these templates in conjunction with different frameworks and libraries such as Angular, React, and Redux.

これらのテンプレートは、次のコマンドを実行して .NET Core CLI を使用してインストールできます。These templates can be installed via the .NET Core CLI by running the following command:

dotnet new --install Microsoft.AspNetCore.SpaTemplates::*

使用可能な SPA テンプレートの一覧が表示されます。A list of available SPA templates is displayed:

テンプレートTemplates 短い形式の名前Short Name 言語Language TagsTags
Angular と ASP.NET Core の MVCMVC ASP.NET Core with Angular angularangular [C#][C#] Web/MVC/SPAWeb/MVC/SPA
React.js 付きの ASP.NET Core の MVCMVC ASP.NET Core with React.js reactreact [C#][C#] Web/MVC/SPAWeb/MVC/SPA
MVC の ASP.NET Core react.js と ReduxMVC ASP.NET Core with React.js and Redux reactreduxreactredux [C#][C#] Web/MVC/SPAWeb/MVC/SPA

SPA テンプレートのいずれかを使用して新しいプロジェクトを作成するには含める、短い名前内のテンプレートの新しい dotnetコマンド。To create a new project using one of the SPA templates, include the Short Name of the template in the dotnet new command. 次のコマンドでは、サーバー側用に構成された ASP.NET Core MVC で Angular アプリケーションを作成します。The following command creates an Angular application with ASP.NET Core MVC configured for the server side:

dotnet new angular

ランタイムの構成モードを設定します。Set the runtime configuration mode

2 つのプライマリのランタイム構成モードは次のとおりです。Two primary runtime configuration modes exist:

  • 開発:Development:
    • デバッグを容易にするソース マップが含まれています。Includes source maps to ease debugging.
    • パフォーマンスのクライアント側のコードを最適化しません。Doesn't optimize the client-side code for performance.
  • 実稼働:Production:
    • ソース マップを除外します。Excludes source maps.
    • バンドルと縮小を使用してクライアント側のコードを最適化します。Optimizes the client-side code via bundling and minification.

ASP.NET Core という環境変数を使用してASPNETCORE_ENVIRONMENT構成モードを格納します。ASP.NET Core uses an environment variable named ASPNETCORE_ENVIRONMENT to store the configuration mode. 詳細については、次を参照してください。環境を設定します。For more information, see Set the environment.

.NET Core CLI を実行します。Run with .NET Core CLI

プロジェクトのルートで、次のコマンドを実行してには、必要な NuGet と npm パッケージを復元します。Restore the required NuGet and npm packages by running the following command at the project root:

dotnet restore && npm i

ビルドし、アプリケーションを実行します。Build and run the application:

dotnet run

アプリケーションの起動時に従い、localhost 上で、ランタイム構成モードします。The application starts on localhost according to the runtime configuration mode. 移動するhttp://localhost:5000ブラウザーにランディング ページが表示されます。Navigating to http://localhost:5000 in the browser displays the landing page.

Visual Studio 2017 での実行します。Run with Visual Studio 2017

開く、 .csprojによって生成されたファイル、新しい dotnetコマンド。Open the .csproj file generated by the dotnet new command. 必要な NuGet と npm パッケージは、プロジェクトを開くと自動的に復元されます。The required NuGet and npm packages are restored automatically upon project open. この復元プロセスは、数分かかる場合があり、アプリケーションが完了するときに実行する準備ができます。This restoration process may take up to a few minutes, and the application is ready to run when it completes. キーを押して、緑色の実行 ボタンをクリックしますCtrl + F5、し、アプリケーションのランディング ページで、ブラウザーが開かれます。Click the green run button or press Ctrl + F5, and the browser opens to the application's landing page. アプリケーションによる localhost で実行、ランタイム構成モードします。The application runs on localhost according to the runtime configuration mode.

アプリのテストTest the app

SpaServices テンプレートは、事前構成を使用してクライアント側のテストを実行してKarmaJasmineします。SpaServices templates are pre-configured to run client-side tests using Karma and Jasmine. Jasmine は、Karma テスト ランナーはこれらのテストには、人気のある単位の JavaScript 用のテスト フレームワークです。Jasmine is a popular unit testing framework for JavaScript, whereas Karma is a test runner for those tests. Karma を使用するように構成、 Webpack 開発ミドルウェアされるよう、開発者が停止し、変更されるたびにテストを実行するために必要はありません。Karma is configured to work with the Webpack Dev Middleware such that the developer isn't required to stop and run the test every time changes are made. テスト_ケースまたはテスト ケース自体に対して実行されるコードであるかどうか、テストが自動的に実行されます。Whether it's the code running against the test case or the test case itself, the test runs automatically.

Angular アプリケーションを使用して、例として、2 つの Jasmine テスト_ケースが既に提供されている、CounterComponentで、 counter.component.spec.tsファイル。Using the Angular application as an example, two Jasmine test cases are already provided for the CounterComponent in the counter.component.spec.ts file:

it('should display a title', async(() => {
    const titleText = fixture.nativeElement.querySelector('h1').textContent;
    expect(titleText).toEqual('Counter');
}));

it('should start with count 0, then increments by 1 when clicked', async(() => {
    const countElement = fixture.nativeElement.querySelector('strong');
    expect(countElement.textContent).toEqual('0');

    const incrementButton = fixture.nativeElement.querySelector('button');
    incrementButton.click();
    fixture.detectChanges();
    expect(countElement.textContent).toEqual('1');
}));

コマンド プロンプトを開き、 ClientAppディレクトリ。Open the command prompt in the ClientApp directory. 次のコマンドを実行します。Run the following command:

npm test

スクリプトで定義されている設定を読み取り、Karma テスト ランナーを起動する、 karma.conf.jsファイル。The script launches the Karma test runner, which reads the settings defined in the karma.conf.js file. その他の設定の間で、 karma.conf.js経由で実行するテスト ファイルを識別します。 そのfiles配列。Among other settings, the karma.conf.js identifies the test files to be executed via its files array:

module.exports = function (config) {
    config.set({
        files: [
            '../../wwwroot/dist/vendor.js',
            './boot-tests.ts'
        ],

アプリの発行Publish the app

デプロイの準備完了パッケージに生成されたクライアント側アセットと発行された ASP.NET Core の成果物を組み合わせることは面倒なことができます。Combining the generated client-side assets and the published ASP.NET Core artifacts into a ready-to-deploy package can be cumbersome. さいわいにも、SpaServices がという名前のカスタム MSBuild ターゲットとそのパブリケーション全体のプロセスを調整RunWebpack:Thankfully, SpaServices orchestrates that entire publication process with a custom MSBuild target named RunWebpack:

<Target Name="RunWebpack" AfterTargets="ComputeFilesToPublish">
  <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
  <Exec Command="npm install" />
  <Exec Command="node node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod" />
  <Exec Command="node node_modules/webpack/bin/webpack.js --env.prod" />

  <!-- Include the newly-built files in the publish output -->
  <ItemGroup>
    <DistFiles Include="wwwroot\dist\**; ClientApp\dist\**" />
    <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
      <RelativePath>%(DistFiles.Identity)</RelativePath>
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
    </ResolvedFileToPublish>
  </ItemGroup>
</Target>

MSBuild ターゲットでは、次の責任があります。The MSBuild target has the following responsibilities:

  1. Npm パッケージを復元します。Restore the npm packages.
  2. サード パーティ製のクライアント側の資産の運用グレードのビルドを作成します。Create a production-grade build of the third-party, client-side assets.
  3. カスタムのクライアント側の資産の運用グレードのビルドを作成します。Create a production-grade build of the custom client-side assets.
  4. Webpack で生成された資産を発行フォルダーにコピーします。Copy the Webpack-generated assets to the publish folder.

MSBuild ターゲットが実行するときに呼び出されます。The MSBuild target is invoked when running:

dotnet publish -c Release

その他の技術情報Additional resources