Angular
GDG Vigo


Hugo Estévez Rocha
Twitter: @hugoerdev
LinkedIn: hugoer85
Freelance frontend developer
- Vanilla JS
- WebComponents
- Angular
- Ionic
- HTML/CSS


Arquitectura de la aplicación

Carpetas y ficheros principales
- components
- layout
- pages
- core
- shared
- app.routing-module.ts
- app.module.ts

Components
- Componentes reutilizables en toda la aplicación (componentes de presentación)
- Mínimas dependencias de terceros
- Total independencia de rutas, estado de la aplicación y del estado del usuario

Layout
- Componentes que generan el shell de la aplicación
- Componentes de presentación


Pages
- Contenido de la aplicación (content)
- Responden al routing
- Contenedores
- Utilizan los componentes de la carpeta de primer nivel "components"

Core
- directives
- guards
- handlers
- language
- login
- service

Core - directives
Directivas usadas en cualquier parte de la aplicación

Core - guards
- Servicios que se encargan de la validación del routing.
- Estrategia de "precarga" de módulos



Core - handlers
- Gestión global de errores
- Gestión de eventos ajenos a los propios de los componentes ( eventManager )
- Interceptores

Core - handlers - error
Cualquier error de javascript (No de HTTP) se mostrará en una notificación en pantalla


Core - handlers - eventManager
Sistema utilizando observables que permite emitir cualquier evento desde cualquier componente y suscribirse desde otro.
Totalmente reemplazable por Redux, pero si no se utiliza dicho patrón, se puede hacer uso de este gestor de eventos.

Core - handlers - eventManager


Core - handlers - interceptores HTTP
Encargado de gestionar todo lo relacionado con las llamadas HTTP.
- Interceptar la llamada ajax para incluir el token
- Encargado de disparar el spinner de forma automática
- Notificar al usuario el resultado de la llamada ajax en base al código de estado del API.

Core - language
- Encargados de configurar el servicio de traducción de angular (@ngx-translate)
- Gestionar cambios de idioma
- Actualizar el título (title meta tag y toolbar del shell de la aplicación) en cada evento de routing
- Utilizar el gestor propio de Angular para avisar de traducciones inexistentes

Core - service
Servicios generales a toda la aplicación
Principamente servicios singleton


Shared
Definición del módulo compartido entre todos los módulos de la aplicación



app.routing.module.ts
Módulo encargado de gestionar el enrutado hacia otros módulos
No debe conocer más componentes que el componente del shell en el que se irán cargando las páginas gracias al router


app.module.ts
Módulo principal de la aplicación
Sólo debe cargar el AppComponent, CoreModule y AppRoutingModule.


Material Design
- Construir tema personalizado utilizando los colores principales tanto en los componentes Material como en los de la aplicación
- Uso en cada módulo

Material Design
styles.scss (principal de la aplicación angular)
Importamos el fichero _themins.scss

Usamos la función mat-core() del fichero _theming.scss


Material Design
Definimos la paleta de colores


Material Design
Creamos el tema

Con esto tenemos en el fichero styles.CSS ya el tema compilado

Material Design
Para incorporar los componentes de Material podemos seguir dos estrategias en base a nuestras necesidades:
- Crear un módulo compartido en la carpeta shared en el que definamos los componentes que se usarán en la aplicación
- En cada módulo de la aplicación (routing) incluir los componentes que serán utilizados por los páginas

Material Design

Ejemplo de cómo he insertado los módulos de los componentes material en la carpeta "components"

PWA
Para generar el service worker para que nuestra aplicación sea una PWA debemos ejecutar el comando:
ng add @angular/pwa
Esto añadirá los paquetes npm necesarios, realizará cambios mínimos en la aplicación (angular.json, app.module.ts) y generará el fichero ngsw-config.json

PWA - manifest.json
Aquí se indica el nombre, colores y todo lo necesario para que los teléfonos (por ejemplo) puedan generar el icono (escritorio y menú), color de fondo al cargar la PWA y en chrome, qué color tendrá la barra del menú


PWA - manifest.json
Hay que añadir el icono de la aplicación en diferentes tamaños, para que el dispositivo presente el icono con el aspecto correcto en cada momento.



PWA - ngsw.config.json
Este fichero es donde podemos configurar qué y cómo queremos gestionar la caché (recursos y llamadas ajax)
assetGroups

dataGroups


PWA - ngsw.config.json
dataGroups
Angular nos permite trabajar con dos estrategias en lo referente a las llamadas ajax
- freshness: El service worker realizará la llamada ajax, y si no tiene conexión, y lo tiene cacheado, devolverá el resultado cacheado
- performance: Antes de realizar la llamada ajax, consultará a la caché si hay respuesta a dicha llamada, en caso afirmativo, devuelve dicho resultado

PWA - ngsw.config.json
assetGroups
- prefetch: precarga los recursos indicados para que estén lo antes disponibles siempre (incluso offline)
- lazy: solicita y cachea los recursos según son requeridos

PWA
Diferentes estrategias para trabajar con serviceworkers


PWA
Diferentes estrategias para trabajar con serviceworkers


PWA
Diferentes estrategias para trabajar con serviceworkers


PWA
En este post está toda la información sobre las estrategias en el service worker:

Buenas prácticas
Usar Angular CLI para lo máximo posible.
El equipo de Angular esté trabajando muchísimo en los tiempos de compilación, minificación y configuraciones.

Buenas prácticas
Desarrollar los componentes bajo el patrón Contenedor - Presentador
El componente contenedor es el encargado de realizar las llamadas ajax y tratamiento de datos para pasárselo al componente presentador, que lo único que tiene que hacer es visualizar los datos

Buenas prácticas
Hacer los componentes lo más pequeños y atómicos posible
- Aumenta la reutilización de código
- Incrementa la performance (El ámbito de dicho componente es más pequeño y la propagación de cambios está más controlada)
- Componentes más testeables

Buenas prácticas
Estrategia de detección del cambio
Por defecto, Angular propaga los cambios producidos en un componente a todos sus componentes hijos.
Eso decrementa muchísimo la performance de la aplicación.


Buenas prácticas
Estrategia OnPush

Angular solo propagará los cambios de los @Input(), método markForCheck (ChangeDetectorRef), el uso de Pipes y cambios en objetos inmutables para realizar cambios y actualizar la vista.

Buenas prácticas
Estrategia de detección del cambio
Para asegurarnos que siempre se usa dicha estrategia por defecto (usando Angular CLI), podemos usar angular schematics para indicárselo


Buenas prácticas
Evitar "Memory leaks"
La librería RxJS nos provee de Observables a los que nos suscribimos para facilitar el tratamiento de la asincronía y eventos.
Siempre hay que ejecutar el método unsubscribe() de todos los observables a los que nos hemos suscrito.
Este proceso no se hace automáticamente aunque el componente se haya destruido, lo que provoca una fuga de memoria importante.

Buenas prácticas
Mecanismos para darse de baja del Observale



Buenas prácticas
Mecanismos para darse de baja del Observale

Si estamos seguros que solo queremos ejecutar el callback del subscribe "n" veces, podemos utilizar el pipe "take" de RxJS e indicar el número de veces que queremos que se ejecute

Buenas prácticas
Mecanismos para darse de baja del Observale
Podemos suscribirnos, sólo hasta que se emita otro evento, el cual lo emitimos en el evento ngOnDestroy del componente.




Buenas prácticas
Cargar los módulos del router bajo demanda (LazyLoad)
Angular generará un fichero por cada módulo lazy, lo que provoca un aumento en la carga inicial de la aplicación al tener ficheros más pequeños
Esta funcionalidad nos ayuda a desacoplar el código propio de cada página / funcionalidad del código "core" de la aplicación

Buenas prácticas
En el fichero app.routing-module.ts se define la carga de los módulos (Sin conocer qué contienen dichos módulos)


Buenas prácticas
Link rel="preload"
Si cargamos ficheros estáticos en nuestro index.html, incluir dicha propiedad nos permitirá indicarle al navegador que debe solicitar el recurso para tenerlo lo antes posible.

Buenas prácticas
Carga de fuentes cargadas desde el CSS
Si tenemos fuentes (iconos por ejemplo) que se cargan mediante @font-face, puede retrasar la carga de la página.
Si no es un icono, siempre se puede indicar una tipografía a modo de fallback

Buenas prácticas
Carga de fuentes cargadas desde el CSS
Para no retrasar la carga de la web hasta tener dicho recurso, podemos usar el atributo "font-display: swap"
La web continuará la carga hasta tener el fichero, lo que no debería tardar mucho si es una PWA y la fuente está incluida dentro del assetsGroup

Buenas prácticas
Mejorar "First contentful Paint"


Esto provoca que la app muestre al usuario algo lo antes posible.
Utilizar ese mecanismo para incluir un spinner.
Incluyendo el CSS mínimo en una etiqueta <style></style>

Buenas prácticas
Medir tamaño de los ficheros generados en la compilación

Buenas prácticas
Angular CLI nos permite configurar límites para producir errores y advertencias


Buenas prácticas
Utilizar Webpack Bundle Analyzer para conocer en exactitud el contenido de cada fichero / módulo


Buenas prácticas
Utilizar la compilación AOT (Ahead-of-Time)
- Renderizado mucho más rápido
- Menos llamadas asíncronas (copia el html y CSS dentro del fichero js)
- Evitar descarga de parte del fwk de Angular (Angular compiler)
- Detecta errores dentro del HTML
- Mejora la seguridad de ataques XSS
"Angular Language Service" es una extensión de VS Code que nos ayuda a prevenir errores de compilación AOT

Buenas prácticas
Auditar la aplicación usando la pestaña "audits" de las developer tools de chrome (Lighthouse)

Realiza una serie de diagnósticos y provee de suficiente información como para conocer el motivo de que una aplicación no sea suficientemente rápida

Buenas prácticas
Habilitar GZIP en el servidor para los recursos estáticos (imágenes, fotos, fuentes)
Incluir cabecera cache-control con el valor "max-age=tiempodeseado"
Utilizar HTTP2

Artículos de interés
Twitter (Angular)
Twitter (web)
Angular GDG Vigo
By Hugo Estévez Rocha
Angular GDG Vigo
- 497