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

Para generar la paleta, podemos usar esta herramienta online:

 

http://mcg.mbitson.com

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)

Made with Slides.com