.NET Core + Vue.jsのプロジェクト作成


自分用のメモ代わりにやったことを書いておきます。
ほぼ参考にさせていただいたページのままですが、そちらのほうではMVCプロジェクトで作成していますが、ここではWebAPIプロジェクトで作成するので若干の違いがあります。

環境

  • Visual Studio 2019
  • .NET Core 3.1.1
  • vue cli 4.2.2

プロジェクト作成

ASP.NET Core WebAPIプロジェクトを作成

とりあえず認証等は何もつけずにAPIのみ

Vue.jsプロジェクト作成

作成したプロジェクトのフォルダで以下のコマンドを実行

vue create client-app

default (babel, eslint)を選択

.NET Coreプロジェクトファイルの編集

csprojファイルを以下のように編集

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <None Remove="client-app\**" />
    <Content Remove="client-app\**" />
    <None Include="client-app\**" Exclude="client-app\node_modules\**" />
  </ItemGroup>

  <Target Name="ExecNpmInstall" BeforeTargets="Build" Condition="'$(Configuration)' == 'Debug' And !Exists('client-app\node_modules')">
    <Exec WorkingDirectory="client-app\" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <Exec WorkingDirectory="client-app" Command="npm install" />
    <Exec WorkingDirectory="client-app" Command="npm run build" />

    <ItemGroup>
      <DistFiles Include="client-app\dist\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

</Project>

.NET Core側のSPA用Configとデバッグ用コードの追加

SPA用のパッケージが入っていないのでnugetで以下のパッケージをインストール

  • Microsoft.AspNetCore.SpaServices.Extensions

ConfigureServicesにSPA用の記述を追加

Startup.cs
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            // 追加
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = @"client-app/dist";
            });
        }

ConfigureにSPA用の記述を追加

Startup.cs
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            // 追加
            app.UseSpaStaticFiles();
            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "client-app";
                if (env.IsDevelopment())
                {
                    spa.UseProxyToSpaDevelopmentServer(async () =>
                    {
                        var pi = new ProcessStartInfo
                        {
                            FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd" : "npm",
                            Arguments = $"{(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "/c npm " : "")}run serve",
                            WorkingDirectory = "client-app",
                            RedirectStandardError = true,
                            RedirectStandardInput = true,
                            RedirectStandardOutput = true,
                            UseShellExecute = false,
                        };
                        var p = Process.Start(pi);
                        var lf = app.ApplicationServices.GetService<ILoggerFactory>();
                        var logger = lf.CreateLogger("npm");
                        var tcs = new TaskCompletionSource<int>();
                        _ = Task.Run(() =>
                        {
                            var line = "";
                            while ((line = p.StandardOutput.ReadLine()) != null)
                            {
                                if (line.Contains("DONE  Compiled successfully in "))
                                {
                                    tcs.SetResult(0);
                                }

                                logger.LogInformation(line);
                            }
                        });
                        _ = Task.Run(() =>
                        {
                            var line = "";
                            while ((line = p.StandardError.ReadLine()) != null)
                            {
                                logger.LogError(line);
                            }
                        });
                        await Task.WhenAny(Task.Delay(20000), tcs.Task);
                        return new Uri("http://localhost:8080");
                    });
                }
            });
        }

一応ここまでで動作はしますが、デフォルトだとデバッグ実行した時にWeatherForecastにアクセスするようになっているためプロジェクトのプロパティで以下の画像のブラウザの起動の右にあるテキストボックスを空にします。

実行

デバッグ実行して問題がなければVue.jsプロジェクトのほうのページが開きます。

参考