Información general
Herramientas de desarrollo
Entornos de desarrollo
El entorno de desarrollo integrado es esencial para los desarrolladores de software. La elección de un IDE (Integrated Development Environment) adecuado y la configuración de los plugins y herramientas correctas puede mejorar significativamente la eficiencia y la calidad del desarrollo.
Desde la Agencia no se impone ninguno en particular, entendiendo que es una cuestión de preferencias de cada desarrollador. Visual Studio Code es la opción más popular para el desarrollo de aplicaciones Angular.
Visual Studio Code
Visual Studio Code (VS Code) es un editor de código fuente ligero pero potente ampliamente adoptado por los desarrolladores Angular. Con su enfoque modular, VS Code permite a los usuarios personalizar su entorno de desarrollo a través de extensión de plugins, que abarcan desde soporte para lenguajes de programación hasta herramientas de depuración y control de versiones.
VS Code ofrece características robustas como autocompletado inteligente, integración con Git y soporte para depuración, con un completo soporte de Angular. Además, Visual Studio Code es de código abierto, bajo la licencia MIT, lo que lo convierte en una opción accesible para desarrolladores individuales y equipos que buscan una herramienta flexible y extensible.
Plugin recomendados
- npm intellisense: Autocompleta módulos de npm en las sentencias de importación. Disponible en: https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense
- SonarLint: Mantiene la calidad del código dentro del editor, proporcionando alertas en tiempo real sobre posibles errores y malas prácticas. Disponible en: https://marketplace.visualstudio.com/items?itemName=SonarSource.sonarlint-vscode
- Prettier: Formateador de código que permite imponer un estilo consistente en el código obligando a respetar ciertas reglas. Disponible en: https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
- GitLens: Mejora la integración de Git con características adicionales como el historial de archivos, comparación de ramas y más. Disponible en: https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens
Para el desarrollo con Angular:
- Angular Language Service: Proporciona una experiencia de edición avanzada para plantillas de Angular, incluyendo autocompletado, autocompletado, mensajes de diagnóstico AOT, información rápida e “Ir a la definición”. Disponible en: https://marketplace.visualstudio.com/items?itemName=Angular.ng-template
- Angular Snippets: Añade “snippets” de código Angular para Typescript y HTML. Disponible en: https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2
node y npm
Para desarrollar una aplicación SPA es necesario contar con Node.js, un entorno de ejecución que permite usar JavaScript fuera del navegador, y con npm (Node Package Manager), el gestor de paquetes oficial de Node, que se utiliza para manejar las dependencias en el entorno local de desarrollo.
Se pueden descargar en https://nodejs.org
Para verificar la correcta instalación desde un terminal:
node -v
npm -vEs necesaria una versión de node igual o superior a node20 (20.19.4 es la versión LTS).
Navegador Web
Se puede utilizar cualquier navegador moderno (Chrome, Firefox, Edge, Safari, ...) para comprobar el funcionamiento de la aplicación en desarrollo.
Para realizar pruebas y tareas de depuración, se recomienda emplear el navegador Google Chrome por su sencilla configuración para su utilización con Karma (el test runner* que utiliza Angular por defecto). Su utilización viene preconfigurada por parte de Karma, no siendo necesaria ninguna configuración adicional.
*Test runner: herramienta que se encarga de ejecutar automáticamente las pruebas de software
Desarrollo de la aplicación
Diseño
Utilizar como base la arquitectura de referencia Microfrontend y las normas; realizando un diseño apropiado que tenga en cuenta:
- Estructura de la aplicación: Consultar la arquitectura de referencia para obtener más información sobre los componentes que pueden ser utilizados en la construcción de la aplicación.
- Patrones de arquitectura y diseño: De igual modo en la arquitectura de referencia se puede consultar la información sobre los diferentes patrones que pueden ser aplicados y escoger los que mejor se adapten a las necesidades de la aplicación.
Construcción
Elección del framework de desarrollo
Implementación de la arquitectura Shell + Microfrontends
Existen diversas opciones para para implementar una aplicación con una Shell + Microfrontends. Este enfoque divide la interfaz en microaplicaciones autónomas, mientras la Shell orquesta navegación, comunicación y experiencia común. El resultado es mayor autonomía de equipos, despliegues independientes y la posibilidad de convivir con distintos frameworks sin sacrificar una UX coherente.
El ecosistema ofrece diferentes piezas complementarias para orquestación y enrutado, para cargar Microfrontends y compartir dependencias en tiempo de ejecución, WebComponents, etc. La elección suele venir dada por restricciones organizativas (gobernanza, usabilidad, accesibilidad, seguridad), stack existente, requisitos de aislamiento y objetivos de rendimiento.
A continuación, se presentan diferentes opciones:
- single-spa: agnóstico al framework (React, Vue, Angular, etc.), ciclo de vida claro por microapp, enrutamiento por zonas, probado en producción durante años, compatible con SystemJS/Import Maps. Ideal para shells que montan/desmontan MFs heterogéneos.
- Webpack 5 Module Federation: compartir dependencias en tiempo de ejecución (evita duplicados), “host/remotes” para que la shell consuma MFs independientes, versionado/estrategias de “shared” finas, despliegues independientes sin recompilar todo el shell.
Desde la Agencia se ha seleccionado Module Federation con el objetivo de establecer un framework base para fomentar la reutilización y publicación de distintos componentes para generar sinergias entre proyectos y aplicaciones.
Su elección se ha basado en:
- Dependencias compartidas en tiempo de ejecución entre microfrontends.
Despliegues realmente independientes: los remotes pueden publicarse y actualizarse sin necesidad de redesplegar el contenedor. Esto facilita rollbacks rápidos y evolución gradual de cada microfrontend.
Opciones de Frameworks y Herramientas para Module Federation
Al implementar un enfoque de Microfrontends con Shell + Module Federation, existen varias opciones de frameworks y librerías que facilitan la integración entre aplicaciones:
- Angular + Module Federation: Angular CLI ofrece soporte nativo para Module Federation a través del Angular Architects Module Federation Plugin. Configuración simplificada, integración fluida con Angular Router, soporte oficial y comunidad activa.
- React + Module Federation: React junto con @module-federation/nextjs-mf (para Next.js) o configuración personalizada de Webpack. Ecosistema maduro, soporte para aplicaciones SPA y SSR, integración sencilla con React Router.
- Vue.js + Module Federation: Configuración directa en Vue CLI o Vite + Webpack, apoyándose en librerías como vite-plugin-federation. Ligero y flexible, buen soporte para proyectos nuevos con Vite.
- Vanilla JS + Webpack Module Federation: Uso directo de Webpack 5 con Module Federation sin framework específico. Máxima flexibilidad, control fino sobre la configuración, framework-agnostic.
Desde la Agencia se proporciona un framework propio basado en Angular + Module Federation para facilitar la homogeneidad y reutilización en el desarrollo de nuevas aplicaciones, componentes Shell o componentes microfrontends.
Implementación utilizando ada-fw-webapps como framework de desarrollo
Es el framework proporcionado por la Agencia. Está basado en Native Federation de Angular, que es una implementación “browser-native” del mismo modelo que Module Federation, pero apoyada en ESM e Import Maps. En el contexto de Angular moderno —Angular CLI con esbuild/Vite— permite que la Shell resuelva Microfrontends remotos y comparta dependencias en tiempo de ejecución manteniendo una sola instancia de Angular cuando es posible.
Requisitos
Instalar la versión de Angular definida
Revisar la versión exacta de Angular; para descargar e instalar Angular CLI:
npm install –g @angular/cli@19.2.15Instalar Yeoman CLI
Yeoman es una herramienta que ayuda a iniciar proyectos de software de forma rápida y organizada. Permite generar la estructura básica de una aplicación a partir de plantillas prediseñadas (llamadas generadores), lo que ahorra tiempo y asegura buenas prácticas desde el inicio del desarrollo.
Para su utilización, abrir una terminal e instalar Yeoman globalmente:
npm install -g yoPara verificar la instalación:
yo --versionSe debería ver la versión de Yeoman instalada.
Descargar e instalar en el entorno local el archivo con el proyecto del generador
- Descargar el fichero .tgz con la última versión desde el repositorio de binarios de la Junta (es necesario estar conectado a la VPN): Repositorio
- Instalar el generador globalmente en el entorno local:
npm install -g ./generator-ada-fwk-webapps-1.0.2.tgz- Verificar la instalación; ada-fwk-webapps debe aparecer en la lista:
yo --generatorsGeneración de la solución
Ejecución del arquetipo
El primer paso es la ejecución del arquetipo para obtener la estructura de la aplicación de microfontends. Para ello es necesario verificar que se dispone de conectividad con Artifactory por lo que será necesario estar conectado a la VPN si el equipo local está fuera de la red de la Junta.
En primer lugar, crear un nuevo directorio para el proyecto:
mkdir mi-proyecto-ada
cd mi-proyecto-adaEjecutar el generador Yeoman:
yo ada-fwk-webapps
- Seleccionar MicroFrontend (MFE)
- Dar nombre al proyecto
- Seleccionar Shell App y MFE App si es la primera vez y queremos generar el proyecto completo o Solo MFE App si ya tenemos la Shell y queremos un microfrontend independiente.
- El proyecto se genera automáticamente y se instalan todas las dependencias.
Estructura del Proyecto
La estructura del proyecto sigue un diseño modular basado en Arquitectura Hexagonal, separando claramente las diferentes responsabilidades del código. Este enfoque permite crear aplicaciones escalables, mantenibles y fáciles de extender.
Estructura General
Estructura general de la shell:
src/
├── app/
│ ├── application/ # Casos de uso y servicios de aplicación
│ ├── domain/ # Modelos de dominio y contratos (interfaces)
│ ├── infrastructure/ # Adaptadores como API, servicios HTTP, etc.
│ ├── presentation/ # Componentes standalone (UI)
│ │ ├── components/ # Componentes reutilizables
│ │ ├── pages/ # Páginas de la aplicación (rutas principales)
│ ├── state/ # Configuración de NGRX (estado global)
│ │ ├── actions/ # Acciones NGRX
│ │ ├── effects/ # Efectos NGRX
│ │ ├── reducers/ # Reducers NGRX
│ │ ├── selectors/ # Selectores NGRX
│ │ └── global.store.ts # Store global manejado por la shell
│ ├── app.routes.ts # Configuración de rutas
│ ├── app.config.ts # Configuración principal de la aplicación
│ ├── app.component.ts # Componente principal
│ ├── app.component.html # Template principal
│ └── app.component.scss # Estilos principales
├── assets/ # Recursos estáticos (imágenes, fuentes, etc.)
│ ├── federation.manifest.ts # URLs de los mfes
├── environments/ # Configuración para diferentes entornos (desarrollo/producción)
├── bootstrap.ts # Configuracion de aranque de la aplicación
despliegue/ # configuración de despliegue por entorno
ci.json # configuración para CI
federation.config.js # Configuración de native federation
Estructura general de un mfe:
src/
├── app/
│ ├── application/ # Casos de uso y servicios de aplicación
│ ├── domain/ # Modelos de dominio y contratos (interfaces)
│ ├── infrastructure/ # Adaptadores como API, servicios HTTP, etc.
│ ├── presentation/ # Componentes standalone (UI)
│ │ ├── components/ # Componentes reutilizables
│ │ ├── pages/ # Páginas de la aplicación (rutas principales)
│ ├── state/ # Configuración de NGRX (estado global)
│ │ ├── actions/ # Acciones NGRX
│ │ ├── effects/ # Efectos NGRX
│ │ ├── reducers/ # Reducers NGRX
│ │ ├── selectors/ # Selectores NGRX
│ │ └── local.store.ts # Store local manejado por el mfe
│ ├── app.routes.ts # Configuración de rutas
│ ├── app.config.ts # Configuración principal de la aplicación
│ ├── app.component.ts # Componente principal
│ ├── app.component.html # Template principal
│ └── app.component.scss # Estilos principales
├── assets/ # Recursos estáticos (imágenes, fuentes, etc.)
│ ├── federation.manifest.ts # URLs de los mfes
├── environments/ # Configuración para diferentes entornos (desarrollo/producción)
├── bootstrap.ts # configuración de aranque de la aplicación
despliegue/ # configuración de despliegue por entorno
ci.json # configuración para CI
federation.config.js # Configuración de native federation
Capas de la Arquitectura Hexagonal
Domain (Dominio)
- Contiene los modelos de datos y las interfaces que definen las reglas del negocio.
- Es independiente de Angular y cualquier tecnología, lo que permite reutilizar la lógica en otros entornos si es necesario.
Ubicación: src/app/domain/
Application (Aplicación)
- Implementa los casos de uso y la lógica del negocio.
- Contiene servicios que gestionan la lógica de la aplicación, interactuando con las capas de dominio e infraestructura.
Infrastructure (Infraestructura)
- Contiene los adaptadores necesarios para interactuar con APIs externas, bases de datos, etc.
- Su propósito es proporcionar las dependencias necesarias para los casos de uso definidos en la capa de aplicación.
Ubicación: src/app/infrastructure/
Core
- Servicios y lógica central compartida: autenticación, guards e interceptores.
- Separados en carpetas según tipo.
Ubicación: src/app/core/
Presentation (Presentación)
- Contiene todos los componentes standalone y páginas que forman la interfaz de usuario.
- Los componentes están organizados en:
- components/: Componentes reutilizables (botones, formularios, tablas).
- pages/: Páginas principales del proyecto (Home, Introducción, etc.).
Ubicación: src/app/presentation/
Tema bootstrap de la Junta de Andalucía
Configurar el tema Bootstrap de la Junta de Andalucía dentro del proyecto es muy importante para respetar el Sistema de diseño de la Junta. Este tema consiste en un conjunto de ficheros css y js, que están disponibles en el repositorio portal-jjaa / Tema bootstrap de la Junta de Andalucía · GitLab.
El tema Bootstrap de la Junta de Andalucía se actualiza periódicamente, cuando se introducen novedades en el Sistema de diseño de la Junta de Andalucía o por motivos técnicos (p.ej. para adaptarse a nuevas versiones del framework Bootstrap). Para facilitar el seguimiento, cada versión del tema se identifica con un número siguiendo el formato “X.X.Y” (p.ej. 1.2.6). En este esquema, los dos primeros dígitos (“X.X”) se corresponden con la versión del Sistema de diseño equivalente, mientras que “Y” indica la revisión del tema.
En los proyectos, debes integrar la última versión estable, cuyo número puedes encontrar en el repositorio del tema Bootstrap.
Para la integración, hay dos opciones:
1. Integración directa en el framework
- En el repositorio, selecciona el tag de la última versión.
- En el directorio dist, descarga los recursos css, js y fonts necesarios.
<link href="../dist/css/custom-jda-bootstrap.css" rel="stylesheet">
<link href="../dist/css/fonts.css" rel="stylesheet">
<link href="../dist/css/all.css" rel="stylesheet">
<script src="../dist/js/bootstrap.bundle.min.js">
<script src="../dist/js/jda-js.js">
2. Integración en línea usando el CDN
El servicio CDN de la Junta de Andalucía ofrece dos alternativas para integrar los recursos css y js necesarios:
- Hacer una petición a la API del Servicio de entrega de PT JDA para la Adaptación Gráfica.
- Enlazar directamente a los recursos css y js en línea, sustituyendo X.X.Y por la versión correspondiente (p.ej. 1.2.6)
<link href="https://cdn.juntadeandalucia.es/components/sass/X.X.Y/css/custom-jda-bootstrap.css" rel="stylesheet">
<link href="https://cdn.juntadeandalucia.es/components/sass/X.X.Y/css/fonts.css" rel="stylesheet">
<link href="https://cdn.juntadeandalucia.es/components/sass/X.X.Y/css/all.css" rel="stylesheet">
<script src="https://cdn.juntadeandalucia.es/components/sass/X.X.Y/js/bootstrap.bundle.min.js">
<script src="https://cdn.juntadeandalucia.es/components/sass/X.X.Y/js/jda-js.js">
Si incluyes latest en lugar del número de versión, integrarás siempre la versión más reciente de estos ficheros. No obstante, no se recomienda esta práctica para sistemas en producción (esto es, se recomienda enlazar a una versión determinada), ya que las actualizaciones de versiones podrían generar incidencias en la visualización del producto.
Configuración de la federación
La configuración de la federación entre la Shell y los microfontends se realiza en los ficheros federation.config.js de la Shell y de los MFEs y es esencial para habilitar Native Federation. Este archivo define los módulos que se expondrán y compartirán entre los proyectos.
Configuración en la Shell
El archivo federation.config.js de la Shell expone partes de la aplicación como el estado global y define los paquetes compartidos.
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config');
module.exports = withNativeFederation({
name: 'shell',
exposes: {
'./GlobalStore': './src/app/state/global.store.ts', // Exponer el Global Store desde la Shell
},
shared: {
'@ngrx/store': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@ngrx/effects': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@angular/core': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@angular/common': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@angular/router': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
...shareAll({ singleton: true, strictVersion: false, requiredVersion: 'auto' }),
},
});
Configuración en un MFE
El archivo federation.config.js de un MFE define qué módulos expone y comparte.
const { withNativeFederation, shareAll } = require('@angular-architects/native-federation/config');
module.exports = withNativeFederation({
name: 'mfeApp',
exposes: {
'./Component': './src/app/presentation/mfecount/mfecount.component.ts', // Componente expuesto
'./store': './src/app/state/store.ts', // Estado local
},
shared: {
'@ngrx/store': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@angular/core': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
'@angular/common': { singleton: true, strictVersion: false, requiredVersion: 'auto' },
...shareAll({ singleton: true, strictVersion: false, requiredVersion: 'auto' }),
},
});
Configuración de rutas para cargar los MFEs
El archivo app.routes.ts de la Shell debe configurarse para cargar dinámicamente los módulos de los MFEs utilizando Native Federation.
import { Routes } from '@angular/router';
import { loadRemoteModule } from '@softarc/native-federation-runtime';
export const routes: Routes = [
{
path: 'mfe1',
loadChildren: () =>
loadRemoteModule({
remoteName: 'mfeApp',
exposedModule: './Component',
}).then((m) => m.MfeCountComponent),
},
{ path: '**', redirectTo: '' },
];
Integración del Estado Global con NGRX
El manejo del estado global en la Shell utiliza NGRX para compartir datos entre los microfrontends.
Configuración del Global Store en la Shell
global.store.ts: Define el reducer y el estado inicial.
import { Action, createReducer, on } from '@ngrx/store';
import { increment } from './actions/global.actions';
export interface GlobalState {
count: number;
}
export const initialState: GlobalState = {
count: 0,
};
const _globalReducer = createReducer(
initialState,
on(increment, (state) => ({ ...state, count: state.count + 1 }))
);
export function globalReducer(state: GlobalState | undefined, action: Action) {
return _globalReducer(state, action);
}global.actions.ts: Define las acciones del estado global.
import { createAction } from '@ngrx/store';
export const increment = createAction('[Global] Increment');
Registro del Reducer en la Configuración de la Aplicación
import { provideStore } from '@ngrx/store';
import { globalReducer } from './state/global.store';
const appConfig = { providers: [ provideStore({ global: globalReducer }), ], };
Acceso al Estado desde un MFE
Un MFE puede suscribirse al estado global expuesto por la Shell.
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { selectCount } from './global.selectors';
export class MfeComponent { count$: Observable<number>;
constructor(private store: Store<{ global: { count: number } }>) { this.count$ = this.store.select(selectCount); } }
Comandos de Angular
Este apartado detalla los comandos más importantes de Angular CLI, especialmente los relacionados con Angular y sus nuevas características como los componentes standalone. Estos comandos permiten crear componentes, servicios, modelos y configurar rutas de manera eficiente.
Estos comandos no son exclusivos de Angular; estaban disponibles en versiones anteriores de Angular.
Crear un Componente Standalone
Un componente standalone es un componente independiente que no necesita un módulo asociado.
ng generate component nombre-del-componente –standaloneOpciones útiles:
- --route: Crea automáticamente una ruta para el componente en el archivo de rutas.
- --inline-template: Genera el componente con el HTML en línea.
- --inline-style: Genera el componente con los estilos en línea.
ng generate component home --standalone --route=homeEste comando crea un componente standalone llamado home y lo registra automáticamente en las rutas.
Los servicios en Angular encapsulan lógica de negocio o lógica compartida entre componentes.
ng generate service nombre-del-servicioOpciones útiles:
- --project: Especifica el proyecto donde se generará el servicio (si hay múltiples proyectos).
ng generate service personEsto crea un servicio llamado person.service.ts en la carpeta correspondiente.
Angular CLI no incluye un comando directo para generar modelos, pero puedes crearlo manualmente:
touch src/app/models/nombre-del-modelo.tsEjemplo de contenido del modelo:
export interface Person {
id: number;
name: string;
age: number;
}
Para automatizar esta tarea, se puede crear un script personalizado o usar herramientas de scaffolding adicionales.
Angular permite crear rutas directamente asociadas con un componente standalone.
ng generate component nombre-del-componente --standalone --route=nombre-de-la-ruta
ng generate component profile --standalone --route=profile
Esto genera un componente profile y agrega la ruta /profile automáticamente al archivo app.routes.ts.
Las directivas permiten agregar comportamientos personalizados a elementos HTML.
ng generate directive nombre-de-la-directiva
ng generate directive highlight
Esto genera un archivo highlight.directive.ts para implementar la directiva.
Los pipes se utilizan para transformar datos en las plantillas de Angular.
ng generate pipe nombre-del-pipe
ng generate pipe capitalize
Esto crea un pipe capitalize que puede transformar texto en mayúsculas o cualquier formato deseado.
Aunque Angular promueve los componentes standalone, aún puedes crear módulos si los necesitas.
ng generate module nombre-del-modulo
ng generate module admin
Esto crea un módulo llamado admin dentro de su propia carpeta.
Ejecutar Pruebas
Angular CLI proporciona comandos para ejecutar pruebas unitarias.
ng testPruebas Unitarias con Reporte de Cobertura:
ng test --code-coverage
Construir la Aplicación
Genera una versión optimizada para producción.
ng build --configuration productionEjemplo para desarrollo continuo (watch mode):
ng build --watch --configuration development
Lint y Formateo
Para verificar y corregir problemas de estilo de código:
ng lintFormatear el código con Prettier:
npm run format
Novedades de Angular y Angular CLI
- Componentes Standalone:
- Simplifican la estructura eliminando la necesidad de módulos.
- Facilitan la modularidad y el uso de dependencias específicas en cada componente.
- Optimización del Build:
- Los tiempos de compilación son más rápidos gracias a mejoras en el motor de compilación.
- Soporte para TypeScript 5.x:
- Se incluye compatibilidad con las últimas versiones de TypeScript.
- Integración con Redux DevTools:
- Simplifica la depuración del estado con herramientas avanzadas.
Para obtener más información se recomienda consultar la documentación oficial de Angular CLI y Angular.
Explicación de Scripts
El archivo package.json del proyecto contiene una serie de scripts que automatizan tareas comunes en el desarrollo, como la compilación, pruebas unitarias, linting, y formateo de código. Estos scripts están diseñados para simplificar el flujo de trabajo y mejorar la productividad de los desarrolladores.
A continuación se explica cada script definido en el archivo package.json:
| Script | Comando | Propósito |
|---|---|---|
| ng | ng | Alias para ejecutar comandos de Angular CLI |
| start | ng serve | Inicia el servidor de desarrollo y carga la aplicación en http://localhost:4200 |
| build | ng build | Construye la aplicación para producción en la carpeta dist/ |
| watch | ng build --watch --configuration development | Construye la aplicación en modo desarrollo y observa cambios en tiempo real |
| test | ng test | Ejecuta las pruebas unitarias configuradas con Karma y Jasmine |
| test:coverage | ng test --code-coverage | Ejecuta las pruebas unitarias y genera un reporte de cobertura en coverage/index.html |
| test:headless | ng test --watch=false --browsers=ChromeHeadless | Ejecuta las pruebas unitarias en modo "headless" (sin interfaz gráfica). |
| lint | ng lint | Ejecuta el análisis estático de código para asegurar que cumple con las reglas definidas |
| format | prettier --write "src/**/*.ts" | Formatea automáticamente el código TypeScript usando Prettier |
Pruebas
Herramientas, métodos y estrategias empleadas para garantizar la calidad del proyecto SPA. Las pruebas unitarias están respaldadas por herramientas como Karma, Jasmine.
Pruebas Unitarias
- Karma: Ejecuta las pruebas en navegadores.
- Jasmine: Framework de pruebas que define y organiza los casos de prueba.
Configuración de Pruebas Unitarias
Jasmine no requiere configuración explícita en el proyecto Angular, ya que se integra automáticamente con Karma a través de Angular CLI. Sin embargo, puedes personalizar comportamientos añadiendo configuraciones en los archivos .spec.ts o modificando el archivo karma.conf.js.
Archivo de Configuración: karma.conf.js Este archivo ya incluye karma-jasmine como framework y plugin predeterminado:
module.exports = function (config) {
config.set({
frameworks: [‘jasmine’, ‘@angular-devkit/build-angular’],
plugins: [
require(‘karma-jasmine’),
require(‘karma-chrome-launcher’),
require(‘karma-jasmine-html-reporter’),
require(‘karma-coverage’),
require(‘@angular-devkit/build-angular/build-angular/plugins/karma’),
],
reporters: [‘progress’, ‘kjhtml’],
browsers: [‘Chrome’],
singleRun: false,
});
};
Definición de Casos de Prueba con Jasmine Los casos de prueba se escriben utilizando la función global describe para definir el grupo de pruebas, it para las pruebas individuales, y expect para las expectativas:
describe(‘Grupo de Pruebas’, () => {
it(‘debería sumar correctamente dos números’, () => {
const resultado = 2 + 3;
expect(resultado).toBe(5);
});
});
Ejemplo Completo de Prueba Unitaria para un componente Standalone:
Archivo home.component.spec.ts:
import { TestBed } from ‘@angular/core/testing’;
import { HomeComponent } from ‘./home.component’;
describe(‘HomeComponent’, () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HomeComponent],
}).compileComponents();
});
it(‘debería crearse’, () => {
const fixture = TestBed.createComponent(HomeComponent);
const component = fixture.componentInstance;
expect(component).toBeTruthy();
});
it(‘debería renderizar el título correctamente’, () => {
const fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain(‘Lista de personas’);
});
});
Errores Comunes
En este apartado se describen los errores más comunes que pueden surgir durante el desarrollo, pruebas y despliegue del proyecto SPA, junto con soluciones prácticas para resolverlos. Se organiza por áreas clave como configuración del entorno, ejecución, pruebas y producción.
Errores en la Configuración del Entorno
| Error | Posible Causa | Solución |
|---|---|---|
| "ng: command not found" | Angular CLI no está instalado globalmente | Instala Angular CLI con: npm install -g @angular/cli |
| "Cannot find module '@angular/core'" | Las dependencias no están instaladas correctamente | Ejecuta npm install para instalar las dependencias |
| Versiones incompatibles de Node.js | El proyecto requiere una versión específica de Node.js | Usa un gestor de versiones como nvm para cambiar a la versión recomendada |
| "Prettier not found" o errores de formato | Prettier no está instalado o configurado correctamente | Asegúrate de tener Prettier instalado: npm install --save-dev prettier. |
Errores al hacer el npm install
Error en la librería @matter que es la de referencia del storybook.

Solución:
Crear el archivo .npmrc y añadir siguiente línea en el archivo
@matter:registry=https://nexus.paas.junta-andalucia.es/repository/msd.npm-private/
Errores en la Ejecución
| Error | Posible Causa | Solución |
|---|---|---|
| "Port already in use" al ejecutar npm run start | Otro proceso está usando el puerto 4200 | Cambia el puerto con: npm run start -- --port=4300 |
| "An unhandled exception occurred: Cannot find module" | Dependencias faltantes o incompatibles en el proyecto | Ejecuta npm install o elimina node_modules y reinstala: rm -rf node_modules && npm install |
| "ERROR Error: StaticInjectorError" | Un servicio no está registrado correctamente en el módulo o como providedIn: 'root' | Verifica la configuración de inyección en el archivo del servicio |
| "ExpressionChangedAfterItHasBeenCheckedError" | Cambios en una propiedad después de la detección de cambios inicial | Usa ChangeDetectorRef.detectChanges() o evita actualizar valores en ciclos de vida tardíos |
Errores en Pruebas Unitarias
| Error | Posible Causa | Solución |
|---|---|---|
| "Uncaught Error: Module not found" | Falta importar el módulo o componente necesario en el archivo .spec.ts | Asegúrate de que todos los módulos y dependencias estén importados en TestBed.configureTestingModule |
| Cobertura de código incompleta | Archivos de prueba faltantes o no incluidos en el reporte | Asegúrate de que todos los archivos están probados y que Karma está configurado correctamente |
| "No provider for Service" | El servicio no está registrado en el TestBed | Usa providers: [MyService] en la configuración de TestBed |
Mejores Prácticas para la Resolución de Errores
- Revisar Logs de Error:
- Inspecciona los mensajes de error en la consola o en las herramientas de desarrollo del navegador.
- Pruebas Aisladas:
- Si el error ocurre en un componente o servicio, prueba ese módulo de manera aislada.
- Limpieza del Entorno:
- Limpia y reinstala las dependencias con:
rm -rf node_modules package-lock.json
npm install
- Depuración:
- Usa herramientas como Redux DevTools, depuradores del navegador o console.log estratégicamente para identificar la causa raíz.
Versiones de componentes
- Angular: 18.x
- ngrx: 18.x
- node: 22.x
- npm: 10.x
- Generator-ada-fwk-webapps: 1.0.2
Para revisar la compatibilidad de Angular con otras herramientas y frameworks, puedes visitar: https://angular.dev/reference/versions
Repositorio de código de la aplicación
Cuando se desarrolla una aplicación de microfrontends es obligatorio que el código esté alojado en un repositorio de código remoto que permita el alojamiento de proyectos, la colaboración en equipo, el control de versiones, la automatización de ciertas tareas y la integración con herramientas externas.
Existe un Repositorio de Código corporativo de la Junta de Andalucía de uso obligatorio para todos los proyectos. Además, el correcto uso de este repositorio se encuentra gobernado por una serie de normas que definen la Estrategia de Ramificación del mismo.
En el ámbito de desarrollo de una aplicación de microfrontends tendremos un repositorio de código para la shell y un repositorio para cada uno de los microfrontends que formar parte de la aplicación. Esto nos permite conseguir:
- Independencia en el desarrollo de cada una de las partes de la aplicación.
- Desacoplamiento entre ellas.
- Independencia de despliegue.
Calidad de la aplicación
La construcción de los microfrontales debe de realizarse con un diseño y codificación de calidad. Existen muchos recursos que nos pueden ayudar en ese cometido, pero desde la Agencia si se establece unos criterios normalizados de forma que la medición de la calidad del software no sea subjetiva.
Puede consultar más en información en:
- Certificación de Calidad Estática de Código
- Umbrales de Aceptación permitidos por SonarQube Quality Gates
Construcción y despliegue
En el caso de los proyectos que están almacenado en el Repositorio de Código asociado a la Plataforma de Pre-Cloud, estaría integrado en la Plataforma de CI/CD, el cual tendrá un Pipeline asociado al proyecto que se encargará de realizar todo el proceso, desde la construcción, pruebas hasta el despliegue en la plataforma de destino.
Para el correcto despliegue de la Shell o de un mfe, estos deben tener configurado los siguientes elementos:
- Fichero dockerfile: Contiene la imagen base para el despliegue del componente y cualquier otro elemento necesario para la generación de la imagen.
- Fichero ci.json: Contiene la configuración de los parámetros de entrada para la correcta ejecución del pipeline de Jenkins.
- Directorio despliegue: Este directorio contiene una carpeta para cada entorno (test, pre y pro). Cada carpeta contiene los ficheros necesarios para el despliegue en ese entorno. El contenido de esta carpeta sigue el patrón de despliegue de Kubernetes Kustomize.
Para iniciar el proceso de despliegue hay que seguir el procedimiento indicado en la documentación relativa a la estrategia de ramificación y verificar tanto en Jenkins como en ArgoCD y Openshift que el proceso de despliegue se está ejecutando correctamente.
Configuración despliegue MFE
Para que la comunicación entre la shell y el MFE sea correcta en el entorno de despliegue debemos habilitar CORS en el fichero de configuración de NGINX del MFE.
Ejemplo de configuración del fichero nginx.conf del MFE:
...
server {
server_name DOMINIO_MFE #p.ej. mfeapp-map—reute-test.apps.paas-des-cica.junta-andalucia.es;
...
location / {
...
# Headers CORS para permitir peticiones desde la shell
add_header ‘Access-Control-Allow-Origin’ ‘DOMINIO_SHELL’ always; #p.ej. ‘https://poc-map-shell-route-test.apps.paas-des-cica.junta-andalucia.es’
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, PUT, DELETE, OPTIONS’ always;
add_header ‘Access-Control-Allow-Headers’ ‘Origin, Content-Type, Accept, Authorization’ always;
# Manejar peticiones OPTIONS para preflight CORS
if ($request_method = ‘OPTIONS’) {
add_header ‘Access-Control-Allow-Origin’ ‘DOMINIO_SHELL’ always;
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, PUT, DELETE, OPTIONS’ always;
add_header ‘Access-Control-Allow-Headers’ ‘Origin, Content-Type, Accept, Authorization’ always;
add_header ‘Access-Control-Max-Age' 1728000;
add_header ‘Content-Type’ ‘text/plain charset=UTF-8';
add_header ‘Content-Length’ 0;
return 204;
}
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
...
#Headers CORS
add_header ‘Access-Control-Allow-Origin’ ‘DOMINIO_SHELL’ always;
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
}
location ~* \.(woff2?|eot|ttf|otf)$ {
...
#Headers CORS
add_header ‘Access-Control-Allow-Origin’ ‘DOMINIO_SHELL’ always;
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
}
}
Ficheros de configuración de despliegue
Tal y como se ha indicado anteriormente se utiliza el patrón de despliegue de Kubernetes Kustomize para realizar los despliegues de forma automática en los diferentes entornos. Es una herramienta que permite personalizar manifiestos de Kubernetes sin necesidad de usar plantillas.
Para la implementación de este patrón tenemos la carpeta despliegue en la raíz del proyecto conteniendo una carpeta por cada uno de los entornos en los que se puede desplegar (test, pre y pro).
Dentro de cada una de estas carpetas encontramos estos ficheros:
- kustomization.yaml: El archivo principal de Kustomize que define:
- Qué recursos incluir en el despliegue.
- Transformaciones para aplicar.
- Variables de entorno.
- Prefijos/sufijos para los nombres de recursos.
- nombre-app-deploy.yaml: Define el deployment de Kubernetes que especifica:
- Imagen del contenedor a desplegar.
- Número de réplicas.
- Configuración de recursos (CPU, memoria).
- Variables de entorno.
- Health checks.
- Estrategia de despliegue.
- nombre-app-svc.yaml: Define el Service que:
- Expone la aplicación internamente en el cluster.
- Especifica los puertos donde escucha la app.
- Configura el balanceador de carga interno.
- Define el selector para conectar con los pods.
- nombre-app-route.yaml: Define la Route que:
- Expone la aplicación externamente.
- Configura el domnio/URL pública.
- Maneja certificados SSL/TLS.
- Define reglas de enrutamiento HTTP/HTTPS.