# Configurar y generar aplicaciones Angular para múltiples entornos personalizados
Cuando generamos una aplicación con Angular CLI, la plantilla inicial de los ficheros package.json, angular.json y environments.ts solo cuentan de manera predeterminada con la configuración para los entornos de desarrollo y producción, así que ¿cómo podemos extender esa configuración para poder definir nuevos entornos personalizados?
Para ello voy a plantear una serie de cambios sobre dichas plantillas con lo que finalmente tendremos la configuración para cuatro entornos de implementación:
- default: Será el entorno predeterminado de ejecución local.
- development: Será el entorno de desarrollo.
- staging: Será el entorno de preproducción.
- production: Será el entorno de producción.
# Extender la configuración de la plantilla inicial de package.json
Esta es la sección scripts de un fichero package.json estándar de una aplicación Angular:
…,
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
…,
package.json
Y esta sería la misma sección del fichero aplicando las modificaciones que propongo:
…,
"scripts": {
"ng": "ng",
"start": "ng serve -o",
"start:development": "ng serve -o --configuration=development",
"start:staging": "ng serve -o --configuration=staging",
"start:production": "ng serve -o --configuration=production",
"build": "ng build",
"build:development": "ng build --configuration=development",
"build:staging": "ng build --configuration=staging",
"build:production": "ng build --configuration=production",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"stats": "ng build --stats-json & webpack-bundle-analyzer dist/my-app/stats.json"
},
…,
package.json
Y cuyos cambios realizados han sido:
- Se agregan tantos comandos
start
como entornos (start:development
,start:staging
, ystart:production
) con el parámetro--configuration
establecido con el nombre de cada entorno (veremos su explicación cuando veamos el fichero angular.json). - Se agregan tantos comandos
build
como entornos (build:development
,build:staging
ybuild:production
) también con el parámetro--configuration
establecido con el nombre de cada entorno. - Al comando
ng serve
he añadido la opción--o
, que aunque no sea relevante para la configuración por entorno, sí que nos hace más cómoda la ejecución de la aplicación al hacer que se abra automáticamente nuestro navegador predeterminado. - Y para terminar también he añadido como mejora al fichero, más allá de la configuración por entorno, el comando
stats
para el análisis de paquetes npm con webpack.
# Extender la configuración de la plantilla inicial de angular.json
Estas son las secciones architect.build.configurations y architect.serve de un fichero angular.json estándar de una aplicación Angular:
…,
"architect": {
"build": {
...,
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
]
}
}
},
"serve": {
...,
"configurations": {
"production": {
"browserTarget": "my-app:build:production"
}
}
},
...,
}
…,
angular.json
Y estas serían las mismas secciones del fichero aplicando las modificaciones que propongo:
…,
"architect": {
"build": {
...,
"configurations": {
"development": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
]
},
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
]
},
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.production.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
]
},
}
},
"serve": {
...,
"configurations": {
"development": {
"browserTarget": "my-app:build:development"
},
"staging": {
"browserTarget": "my-app:build:staging"
},
"production": {
"browserTarget": "my-app:build:production"
}
}
},
...,
}
…,
angular.json
Y cuyos cambios realizados han sido:
- Bajo la sección architect.build.configurations se agregan tantas configuraciones como entornos personalizados hayamos definido (el default usará la configuración por defecto de desarrollo de Angular, como el fichero environment.ts). Estas configuraciones deben corresponder con los nombres especificados en el parámetro
--configuration
de los comandosstart
ybuild
personalizados que hemos creado en el fichero package.json. Como el fichero ya incluye la configuración production, sólo tenemos que crear las configuraciones development y staging. - En cada configuración creada bajo la sección architect.build.configurations, hemos personalizado los nombres de los ficheros de entorno (sección fileReplacements) que vamos a usar, en nuestro caso environment.development.ts, environment.staging.ts y environment.production.ts (hemos sustituido el nombre del fichero original environment.prod.ts para mantener la coherencia con los nuevos que hemos creado).
- A la sección architect.serve hemos añadido los dos nuevos entornos que nos faltaban (devlopment y staging) dado que el de producción ya estaba creado.
# Extender la configuración de la plantilla inicial de environment.ts
Dado que ya contamos con los ficheros de configuración de entorno environment.ts y environment.prod.ts, lo único que tenemos que hacer es:
- Crear los nuevos ficheros environment.development.ts y environment.staging.ts.
- Modificar el nombre del fichero environment.prod.ts por environment.production.ts.
# Usar la configuración personalizada según entorno de ejecución
A partir de este momento ya podemos arrancar nuestra aplicación o empaquetarla para cada uno de los entornos definidos de la siguiente manera:
npm run start
npm run start:development
npm run start:staging
npm run start:production
npm run build
npm run build:development
npm run build:staging
npm run build:production
En el caso del comando
start
, podríamos obviar el comandorun
que le precede y simplificarlo connpm start
ya que por sí mismostart
es un comando de npm.