Select 正确 Angular 基于 .Net Core 构建的环境

Select correct Angular Environment based on .Net Core build

我使用 Visual Studio 中的模板创建了一个 .Net Core Web Api 和 Angular ClientApp。

构建项目时,还会构建包含的 Angular 应用程序,其参数设置在 .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>

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

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

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

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

或者 Angular 应用程序的 use/override 环境变量是否有另一种(更干净?)方法?

这些是构建期间应该交换的值

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

因为 localhost:5001 在产品中没有可行的选择

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

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

在我发现可以为 dotnet build 添加自定义构建配置后,我将以下行添加到 <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish"> 块:

<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 在 corresponding/appropriate 环境中调用。

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

或者先有 2 个单独的项目,省去麻烦:)

编辑:

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

我只是想提供一个end-to-end解决方案,因为我现在将花费一些时间来拯救你:)。

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

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

其中 Staging 是您所需的环境名称。这将确保您能够在 Visual Studio.

Start 下 select 此配置

更多信息:read this

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

  2. 在您的 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,这是必需的,因为您不想在已部署的环境中执行它,但是对于本地 运行ning angular,您必须调用它, 否则你会得到一个错误页面。您可能还注意到,我将 debug 附加到环境名称,我稍后会解释。现在你必须意识到 env.IsDevelopment() 将是错误的,因此你将不得不努力确保你的 angular 应用程序在 运行 在本地运行你的应用程序时仍然会被构建和服务.

  1. 修改您的 angular.json,在 architect => build => 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,这样它仍然保留源映射,并且我能够在 运行 在本地调试我的代码。

  1. environment.staging.ts 文件添加到 environments 文件夹中,用于 environment-specific 选项。更多信息,read this

  2. 修改你的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 和 运行 内更改为新配置!

  1. 修改您的 .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:ssr -- --prod" Condition=" '$(BuildServerSideRenderer)' == 'true' " />
  <!--rest below here-->

我修改了我的代码以调用我在 package.json 中定义的正确 script,因为出于某种原因,我的 CI使用 pjominet 的回答。

如果您使用的是 Azure DevOps,只需将 BuildConfiguration 变量设置为 Staging。如果您按照所有步骤进行操作,那么应该会成功构建。