Descripción General
Este proyecto utiliza la librería @ngx-env/builder
para manejar variables de entorno de manera segura y eficiente en aplicaciones Angular. Este enfoque permite inyectar variables de entorno durante el proceso de build, manteniendo la seguridad y flexibilidad necesarias para diferentes entornos.
Arquitectura del Sistema
1. Dependencias Principales
El proyecto utiliza las siguientes dependencias clave:
para instalar npm i @ngx-env/builder
{
"dependencies": {
"@ngx-env/builder": "^20.1.1"
}
}
2. Configuración del Builder
En angular.json
, el proyecto está configurado para usar el builder personalizado de @ngx-env:
{
"architect": {
"build": {
"builder": "@ngx-env/builder:application",
"options": {
"browser": "src/main.ts",
"tsConfig": "tsconfig.app.json"
}
},
"serve": {
"builder": "@ngx-env/builder:dev-server"
}
}
}
Proceso de Configuración Paso a Paso
Paso 1: Definir Variables de Entorno
1.1 Crear archivo .env
Puedes crear un archivo .env
en la raíz del proyecto:
# .env
NG_APP_ANGULAR_VALUE=Mi valor de desarrollo
NG_APP_API_URL=https://api-dev.ejemplo.com
NG_APP_VERSION=1.0.0
Paso 2: Definir Tipos TypeScript
En src/env.d.ts
, define las interfaces para tus variables de entorno:
declare interface Env {
readonly NODE_ENV: string;
readonly NG_APP_ANGULAR_VALUE: string;
readonly NG_APP_API_URL: string;
readonly NG_APP_VERSION: string;
[key: string]: any;
}
// Usar _NGX_ENV_ (personalizable)
declare const _NGX_ENV_: Env;
Paso 3: Configurar Archivos de Entorno
3.1 Archivo de Desarrollo (src/environment/environment.ts
)
export const environment = {
production: false,
mensaje: _NGX_ENV_.NG_APP_ANGULAR_VALUE,
apiUrl: _NGX_ENV_.NG_APP_API_URL,
version: _NGX_ENV_.NG_APP_VERSION,
};
3.2 Archivo de Producción (src/environment/environment.prod.ts
)
export const environment = {
production: true,
mensaje: _NGX_ENV_.NG_APP_ANGULAR_VALUE,
apiUrl: _NGX_ENV_.NG_APP_API_URL,
version: _NGX_ENV_.NG_APP_VERSION,
};
Paso 4: Usar Variables en el Código
Tutorial para el paso 4 tambien util
4.1 Importar el entorno
import { environment } from './environment/environment';
export class MiComponente {
constructor() {
console.log('Mensaje:', environment.mensaje);
console.log('API URL:', environment.apiUrl);
console.log('Versión:', environment.version);
}
}
Convenciones de Nomenclatura
Variables de Entorno
-
Prefijo obligatorio: Todas las variables deben comenzar con
NG_APP_
-
Ejemplos válidos:
NG_APP_API_URL
NG_APP_VERSION
NG_APP_DEBUG_MODE
Variables del Sistema
-
NODE_ENV
: Se configura automáticamente -
NG_APP_*
: Variables personalizadas de la aplicación
Comandos de Build y Desarrollo
my-angular-app
└── src
└── environments
├── environment.ts
├── environment.development.ts
├── environment.pilot.ts
└── environment.production.ts
Ahora tendras que modificar el angular.json
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true
},
"development": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
}
],
"optimization": false,
"sourceMap": false,
"extractCss": true,
"namedChunks": false
}
},
"pilot": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true
},
"development": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
}
],
"optimization": false,
"sourceMap": false,
"extractCss": true,
"namedChunks": false
}
}
En el mismo archivo angular.json
tendras que modificar el serve
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "my-angular-app:build:production"
},
"development": {
"buildTarget": "my-angular-app:build:development"
},
"pilot": {
"buildTarget": "my-angular-app:build:pilot"
},
},
"defaultConfiguration": "development"
},
Luego tendras que agregar los comandos personalizados package.json
{
"name": "my-angular-app",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"start:dev": "ng serve --configuration=development",
"start:pilot": "ng serve --configuration=pilot",
"start:prod": "ng serve --configuration=production",
"build:dev": "ng build --configuration=development",
"build:pilot": "ng build --configuration=pilot",
"build:prod": "ng build --configuration=production"
},
"private": true,
"dependencies": {
...
},
"devDependencies": {
...
}
}
⚠️ Limitaciones Importantes
Variables Secretas - NO RECOMENDADO
Este enfoque NO es seguro para variables secretas por las siguientes razones:
1. Exposición en el Cliente
- Las variables se inyectan en tiempo de build
- Se incluyen en el bundle JavaScript final
- Son visibles para cualquier usuario que inspeccione el código
2. Acceso Público
// ❌ NUNCA hagas esto con secretos
export const environment = {
apiKey: _NGX_ENV_.NG_APP_SECRET_KEY, // ¡VISIBLE EN EL CLIENTE!
};
3. Alternativas Seguras para Secretos
Para variables secretas, usa:
- Backend Proxy: El frontend solicita datos al backend, que maneja los secretos
- API Keys Públicas: Solo para APIs que requieren keys públicas
- Autenticación JWT: Tokens temporales generados por el backend
- Variables de Servidor: Configurar en el servidor web (nginx, Apache)
Ejemplo de Implementación Segura:
// ❌ Incorrecto - secreto en el frontend
const secretKey = _NGX_ENV_.NG_APP_SECRET_KEY;
// ✅ Correcto - solicitar al backend
this.http.get('/api/data').subscribe(data => {
// El backend maneja los secretos
});
Casos de Uso Apropiados
✅ Variables Seguras para el Cliente
- URLs de APIs públicas
- Configuraciones de UI
- Versiones de aplicación
- Flags de características
- Configuraciones de entorno (dev/staging/prod)
❌ Variables que NO deben usarse
- API keys secretas
- Tokens de autenticación
- Credenciales de base de datos
- Claves de encriptación
- Cualquier información sensible
Mejores Prácticas
-
Prefijo consistente: Siempre usa
NG_APP_
-
Tipado fuerte: Define interfaces en
env.d.ts
- Valores por defecto: Proporciona fallbacks cuando sea posible
- Documentación: Documenta todas las variables requeridas
- Validación: Valida variables críticas en tiempo de ejecución
Ejemplo Completo
Estructura de archivos:
src/
├── env.d.ts
├── environment/
│ ├── environment.ts
│ └── environment.prod.ts
└── app/
└── mi-componente.ts
Configuración completa:
// env.d.ts
declare interface Env {
readonly NG_APP_API_URL: string;
readonly NG_APP_VERSION: string;
readonly NG_APP_DEBUG: string;
}
declare const _NGX_ENV_: Env;
// environment.ts
export const environment = {
production: false,
apiUrl: _NGX_ENV_.NG_APP_API_URL || 'http://localhost:3000',
version: _NGX_ENV_.NG_APP_VERSION || '1.0.0',
debug: _NGX_ENV_.NG_APP_DEBUG === 'true',
};
Este enfoque proporciona una solución robusta y segura para manejar variables de entorno en aplicaciones Angular, manteniendo la separación entre configuraciones públicas y secretos sensibles.
Top comments (0)