首页 > 解决方案 > 发布 .netcore 角度项目给出“SPA 默认页面中间件无法返回 index.html”,在调试中工作

问题描述

我们继承了一个小型 .net 核心应用程序,它有一个 Angular 8 前端和一个 web api 后端。当我收到文件时,它们是两个独立的项目,但为了使它们与我们的其他项目相似,并使我们的部署更容易,我们希望将它们组合成一个 Visual Studio 解决方案/项目。

我已经将文件带入了 Visual Studio 并做了各种事情来尝试让项目正常工作。我已经做了一天了,所以我不能完全告诉你我到底尝试了什么。目前,当我调试它时一切正常,完全没有问题,一切正常。但是,如果我发布文件,我最终会遇到加载网站会出现以下错误的问题:

 [Error] An unhandled exception has occurred while executing the request.
System.InvalidOperationException: The SPA default page middleware could not return the default page '/index.html' because it was not found, and no other middleware handled the request.
Your application is running in Production mode, so make sure it has been published, or that you have built your SPA manually. Alternatively you may wish to switch to the Development environment.

   at Microsoft.AspNetCore.SpaServices.SpaDefaultPageMiddleware.<>c__DisplayClass0_0.<Attach>b__1(HttpContext context, Func`1 next)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)

查看已发布的文件,.net 核心和 Web API 文件似乎是正确的。但是,在 ClientApp 文件夹中,文件看起来不正确(与另一个项目 Angular 8 和 WebAPI 相比)。

首先,我完全错过了 dist 文件夹。我相信这样做的原因是没有生成 dist 文件,因为如果我比较两个 Visual Studio 解决方案(以及它们的项目路径 - 而不是发布路径);工作项目有 index.html、runtime.xxx.js 和 main.xxx.js 等文件。非工作项目没有这些文件,而是只有一个 out-tsc 文件夹,其中包含编译为 javascript 的 typescript 文件的副本。

其次,非工作项目的已发布 ClientApp 文件夹包含 angular.json、tsconfig.json 和几个其他 JSON 文件,这些文件不存在于工作项目发布的文件中。

它似乎与打字稿文件的发布或生成特别相关,但我不确定如何解决它。

一些可能会增加有价值的细节的事情:

startup.cs 的一部分具有以下内容:

services.AddSpaStaticFiles(configuration =>
{
   configuration.RootPath = "ClientApp/dist";
});

// *snip* 

app.UseSpaStaticFiles();

app.UseSpa(spa => {
    spa.Options.SourcePath = "ClientApp";
    if (env.IsDevelopment())
    {
        spa.UseAngularCliServer(npmScript: "start");
    }
});

angular.json 的一部分:

  "outputPath": "dist"

完整的 tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  }
}

标签: angulartypescriptvisual-studioasp.net-web-api2publish

解决方案


因此,在逐行比较我的 csproj 文件后,我最终将以下内容添加到非工作 csproj。然后抱怨另一个小错误(实际上是代码错误),然后一切都开始正常工作。

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build -- --prod" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)dist\**; $(SpaRoot)dist-server\**" />
      <DistFiles Include="$(SpaRoot)node_modules\**" Condition="'$(BuildServerSideRenderer)' == 'true'" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>%(DistFiles.Identity)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>

推荐阅读