根据 .Net Core 构建选择正确的 Angular 环境

Posted

技术标签:

【中文标题】根据 .Net Core 构建选择正确的 Angular 环境【英文标题】:Select correct Angular Environment based on .Net Core build 【发布时间】:2019-08-29 13:50:52 【问题描述】:

我使用来自 Visual Studio 的模板创建了一个带有 Angular ClientApp 的 .Net Core Web Api。

在构建项目时,还会使用 .csproj 部分中设置的参数构建包含的 Angular App,例如

<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:s-s-r -- --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>

(此部分是在创建新项目时自动生成的)

然而,这让我别无选择应该在构建期间使用来自 Angular 的哪个 environment.ts 文件,这使得针对不同部署目标的构建有点复杂。

有没有办法在构建过程中动态设置这个文件?例如

appsettings.json 应该使用 environment.ts 构建 appsettings.Development.json 应该使用 environment.dev.ts 构建 appsettings.Production.json 应该使用 environment.prod.ts 构建 等

这将确保每个 dotnet 构建及其对应的 Angular 构建都具有 api-url、版本等的正确环境值...

或者是否有另一种(更清洁的?)方法来使用/覆盖 Angular 应用程序的环境变量?

这些是在构建过程中应该交换的值

export const environment = 
    production: false,
    dataServiceURI: 'https://localhost:5001/data',
    version: 'localhost'
;

例如,由于 localhost:5001 在 prod 中是不可行的选择

【问题讨论】:

我不了解 .NET 部分,但您可以使用不同的命令使用不同的目标元素,例如 npm run build 选择 environment.ts 或 npm run build --configuration=dev 选择 environment.dev.ts .您必须在 angular.json 文件中定义配置。 对于这种方法,我不太了解 .csproj xml 的结构,无法轻松操作它。我试过了,但失败得很惨 【参考方案1】:

毕竟,我通过操作 *.csproj 找到了解决方案。

提示:需要明确的是,此问题仅适用于您使用Visual Studio .Net Core Web Api with Angular Template 创建项目时,该Visual Studio .Net Core Web Api with Angular Template 创建了一个与clientapp 项目组合的Web api

在我发现我可以为dotnet build 添加自定义构建配置后,我在&lt;Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish"&gt; 块中添加了以下几行:

<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build-prod" Condition="'$(Configuration)' == 'Release'" />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm run build-staging" Condition="'$(Configuration)' == 'Staging'" />

并在 package.json 添加到脚本:

"scripts": 
        "build-staging": "ng build --configuration=staging",
        "build-prod": "ng build --configuration=production",
    ,

它的作用是在 Condition 属性设置的不同构建配置上,npm run build 使用相应/适当的环境调用。

另一种可能更简单的方法是有两个构建管道,一个用于 npm 和 angular 应用程序,一个用于 dotnet web api。这样做时,您可能希望从 *.csproj 中删除整个构建 SPA 内容,否则它将构建应用程序两次。

或者一开始就拥有 2 个独立的项目,省去自己的麻烦 :)

编辑:

正如所指出的Command="npm run build --configuration=production"(例如,使用多个参数构建)不会被 CI/CD 拾取。所以使用 package.json 中的预定义脚本是正确的方法:)

【讨论】:

Command="npm run build -- --configuration=production" 应该可以工作(注意参数前的“--”【参考方案2】:

我只想提供一个端到端的解决方案,因为我现在会为您节省一些时间:)。

我的目标是为不同的公司提供不同的环境配置,因为只需稍作改动(启用/禁用模块、更改徽标、更改主题颜色等),不同公司将使用 Web 应用程序。

    配置 launchSettings.json(在您的 Web 项目中的属性下)。在profiles下添加如下代码:
"Staging": 
 "commandName": "IISExpress",
 "launchBrowser": true,
 "environmentVariables": 
   "ASPNETCORE_ENVIRONMENT": "Staging"
 ,
 "applicationUrl": "https://localhost:5001;http://localhost:5000"

如果您想要的环境名称,Staging 是名称。这将确保您能够在 Visual Studio 中的 Start 下选择此配置。

欲了解更多信息:read this

    在项目的根目录中添加您自己的appsettings.Staging.json 文件,用于自定义应用设置。尽管这对于本地测试非常重要,因为在您的 CI/CD 中您可能需要配置 substitutions。如果您确实想在生产中使用特定的appsettings.Staging.json,请在服务器上将ASPNETCORE_ENVIRONMENT 设置为Staging(对于配置=> 应用程序设置下的天蓝色应用服务)。

    在您的 Startup.cs 中,添加以下 else if 块。

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

    if (env.IsDevelopment())
    
        spa.UseAngularCliServer(npmScript: "start");
    
    else if (env.EnvironmentName == "Staging")
    
#if DEBUG
        spa.UseAngularCliServer(npmScript: "start-stagingdebug");
#endif
    
);

请注意#if DEBUG,这是必需的,因为您不想在已部署的环境中执行此操作,但是对于本地运行的 Angular,您必须调用它,否则您最终会出现错误页面。您可能还注意到,我将debug 附加到环境名称中,稍后我会解释。现在您必须意识到env.IsDevelopment() 将是错误的,因此您必须努力确保在本地运行您的应用程序时仍然可以构建和服务您的 Angular 应用程序。

    修改你的angular.json,在architect =&gt; build =&gt; configurations下,添加2个新配置:
"staging": 
  "fileReplacements": [
    
      "replace": "src/environments/environment.ts",
      "with": "src/environments/environment.toptechneut.ts"
    ,
    
      "replace": "src/assets/img/logo-icon.png",
      "with": "src/assets/img/staging/logo-icon.png"
    ,
  ],

  "optimization": true,
  "outputHashing": "all",
  "sourceMap": false,
  "extractCss": true,
  "namedChunks": false,
  "aot": true,
  "extractLicenses": true,
  "vendorChunk": false,
  "buildOptimizer": true,
  "budgets": [
    
      "type": "initial",
      "maximumWarning": "2mb",
      "maximumError": "5mb"
    
  ]
,
"stagingdebug": 
  "fileReplacements": [
    
      "replace": "src/environments/environment.ts",
      "with": "src/environments/environment.toptechneut.ts"
    ,
    
      "replace": "src/assets/img/logo-icon.png",
      "with": "src/assets/img/staging/logo-icon.png"
    ,
  ]

如果您对angular.json 有所了解,您会注意到在staging 中我为生产环境进行了配置,我将确保我的CI/CD 会调用它(或者当我通过VS2017 发布我的应用程序时)。对于本地测试,我持有不同的配置stagingdebug,因此它仍然保留源映射,并且我能够在本地运行时调试我的代码。

    environments 文件夹中添加您的environment.staging.ts 文件,以获得特定于环境的选项。更多信息,read this

    修改你的package.json,在scripts下,我添加了这些脚本:

"start-staging": "ng serve --configuration staging",
"start-stagingdebug": "ng serve --configuration stagingdebug",
"build-staging": "ng build --configuration staging",
"build-stagingdebug": "ng build --configuration stagingdebug",

这里也一样:对于本地开发,我调用带有 debug 附加到它的配置。

到目前为止,您应该可以在 Visual Studio 中更改为新配置并根据您的新环境配置运行!

    修改您的.csproj,感谢您的pjominet。请注意,这仅用于发布您的 Web 应用程序,而不用于本地调试。
<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-core" />
 <Exec WorkingDirectory="$(SpaRoot)" Command="npm run buildprod" Condition="'$(Configuration)' == 'Release'" />
 <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build-staging" Condition="'$(Configuration)' == 'Staging'" />
 <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build:s-s-r -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />
  <!--rest below here-->

我修改了我的代码以调用我在package.json 中定义的正确script,因为由于某种原因,当我使用 pjominet 的答案时,我的 CI 没有接收到它背后的额外命令。

如果您使用的是 Azure DevOps,您只需将 BuildConfiguration 变量设置为 Staging。如果您遵循了所有步骤,那么这应该会成功构建。

【讨论】:

感谢您指出 CI 不会获取具有多个参数的构建命令,我已经意识到并在我的项目中修复了这个问题,但我忘记更新我的答案,我现在这样做了 :)

以上是关于根据 .Net Core 构建选择正确的 Angular 环境的主要内容,如果未能解决你的问题,请参考以下文章

使用 ASP.NET Core MVC 编辑 Cascade DropDownList

如何在.Net Core启动时根据环境动态选择连接字符串?

在 .Net Core 2.2 中将 HttpResponseMessage 作为 IActionResult 返回的正确方法

.Net Core Visual Studio 项目命令行构建与右键构建相同

asp.net core 选择标签助手

关于 ASP.NET Core 中的授权