Seleccione el entorno angular correcto basado en la compilación .Net Core

13

Creé una .Net Core Web Api con una Angular ClientApp con las plantillas de Visual Studio.

Al construir el proyecto, también construye la aplicación Angular contenida con los parámetros establecidos en la sección .csproj <Target>, por ejemplo

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

(Esta sección se generó automáticamente al crear un nuevo proyecto)

Sin embargo, esto no me deja elegir qué archivo environment.ts de Angular se debe usar durante una compilación, lo que hace que la compilación para diferentes objetivos de implementación sea un poco complicada.

¿Hay alguna forma de configurar este archivo dinámicamente durante la compilación? p.ej

  • appsettings.json debería compilarse con environment.ts
  • appsettings.Development.json debería compilarse con environment.dev.ts
  • appsettings.Production.json debería compilarse con environment.prod.ts
  • etc.

Esto garantizaría que cada compilación de dotnet y su compilación angular correspondiente tuvieran los valores de entorno correctos para la api-url, la versión, etc.

¿O hay otro método (¿más limpio?) Para usar / anular las variables de entorno para la aplicación Angular?

Estos son los valores que deben intercambiarse durante la compilación.

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

Como localhost: 5001 no es una opción viable en prod, por ejemplo

2
  • No sé sobre la parte .NET, pero podría tener diferentes elementos de Target con diferentes comandos, como npm run buildseleccionar environment.ts o npm run build --configuration=devseleccionar environment.dev.ts. Debe tener las configuraciones definidas en su archivo angular.json. 8 de abril de 2019 a las 12:18
  • para este método, no entiendo lo suficiente la estructura del .csproj xml para manipularlo fácilmente. Lo intenté, pero fracasé miserablemente 9 de abril de 2019 a las 8:20
22

Encontré una solución manipulando el * .csproj después de todo.

SUGERENCIA: Para que quede claro, este problema solo se aplica cuando creó su proyecto con el Visual Studio .Net Core Web Api with Angular Templateque crea una api web combinada con el proyecto clientapp

Después de descubrir que podía agregar configuraciones de compilación personalizadas dotnet build, agregué las siguientes líneas al <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">bloque:

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

y en package.json agregar a los scripts:

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

Lo que hace, es en diferentes configuraciones de construcción establecidas por el Conditionatributo, npm run buildse llama con un entorno correspondiente / apropiado.

Otro enfoque, quizás más fácil, sería tener dos pipelines de compilación, uno para npm y la aplicación angular y otro para la api web dotnet. Mientras lo hace, es posible que desee eliminar todo el material SPA de compilación del * .csproj; de lo contrario, compilará la aplicación dos veces.

O simplemente tenga 2 proyectos separados en primer lugar y ahórrese la molestia :)

EDITAR:

Como se señaló Command="npm run build --configuration=production"(por ejemplo, construir con múltiples parámetros) no es recogido por el CI / CD. Entonces, usar scripts predefinidos de package.json es el camino correcto a seguir :)

1
  • Command = "npm run build - --configuration = production" debería funcionar (tenga en cuenta el "-" antes de los parámetros 2 de marzo a las 12:53
13

Solo me gustaría proporcionar una solución de un extremo a otro, porque me llevó bastante tiempo salvarlo ahora :).

Mi objetivo era tener diferentes configuraciones de entorno para diferentes empresas, ya que la aplicación web será utilizada por diferentes empresas con solo pequeños cambios (habilitar / deshabilitar módulos, cambiar logo, cambiar colores de tema, etc.).

  1. Configure launchSettings.json(dentro de su proyecto web en propiedades). Agregue el siguiente código en profiles:
"Staging": {
 "commandName": "IISExpress",
 "launchBrowser": true,
 "environmentVariables": {
   "ASPNETCORE_ENVIRONMENT": "Staging"
 },
 "applicationUrl": "https://localhost:5001;http://localhost:5000"
}

¿Dónde Stagingestá el nombre si el nombre de su entorno deseado? Esto asegurará que pueda seleccionar esta configuración Starten Visual Studio.

Para más información: lea esto

  1. Agregue su propio appsettings.Staging.jsonarchivo en el directorio raíz del proyecto para la configuración personalizada de la aplicación. Aunque esto es más importante para las pruebas locales porque en su CI / CD probablemente querrá configurar sustituciones . Si desea utilizar el específico appsettings.Staging.jsonen producción, configúrelo ASPNETCORE_ENVIRONMENTen Stagingen el servidor (para Azure App Service en Configuración => Configuración de la aplicación).

  2. En su Startup.cs, agregue el siguiente else ifbloque.

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
    }
});

Tenga en cuenta que #if DEBUGesto es necesario porque no desea ejecutar esto en un entorno implementado, sin embargo, para ejecutar angular localmente, TIENE que llamar a esto, de lo contrario, terminará con una página de error. Como también puede notar, agrego debugal nombre del entorno, lo explicaré más adelante. Por ahora, debe darse cuenta de que env.IsDevelopment() será falso y, por lo tanto, tendrá que trabajar para asegurarse de que su aplicación angular aún se compile y se sirva cuando la ejecute localmente.

  1. Modifique su angular.json, en architect => build => configurations, agregue 2 nuevas configuraciones:
"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"
    },
  ]
}

Si sabe un poco sobre angular.jsonusted, observe que en staginghago una configuración para un entorno de producción, me aseguraré de que mi CI / CD llame a esto (o cuando publique mi aplicación a través de VS2017). Para las pruebas locales, tengo una configuración diferente stagingdebug, de modo que aún conserva los mapas de origen y puedo depurar mi código mientras lo ejecuto localmente.

  1. Agregue su environment.staging.tsarchivo dentro de la environmentscarpeta, para opciones específicas del entorno. Más sobre eso, lee esto

  2. modificar su package.json, debajo scripts, agregué estos 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",

Lo mismo aquí: para el desarrollo local llamo a la configuración con un debugapéndice.

¡A partir de ahora, debería poder cambiar a la nueva configuración dentro de Visual Studio y ejecutar de acuerdo con las nuevas configuraciones de su entorno!

Visual Studio elige una configuración diferente para comenzar.

  1. Modifica tu .csproj, gracias por ese pjominet. Tenga en cuenta que, una vez más, esto es solo para publicar su aplicación web, no para la depuración local.
<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-->

Modifiqué el mío para llamar al correcto scriptque definí en mi package.json, porque por alguna razón mi CI no captó los comandos adicionales detrás de él mientras estaba usando la respuesta de pjominet.

Si está utilizando Azure DevOps, solo tiene que cambiar la BuildConfigurationvariable establecida en Staging. Si siguió todos los pasos, esto debería compilarse correctamente.

configuración de compilación de devops azul

1
  • gracias por señalar que CI no recoge comandos de compilación con múltiples parámetros, ya me di cuenta y lo arreglé en mi proyecto, pero olvidé actualizar mi respuesta, lo cual hice ahora :) 13 de mayo de 2019 a las 9:19