Construyendo una PWA usando Angular 6

Publicado: 2022-03-10
Resumen rápido ↬ A lo largo de este tutorial, utilizaremos Angular 6 para crear una aplicación web progresiva, paso a paso, implementando los principios básicos de las PWA mediante Angular CLI v6.

En este tutorial, usaremos el último Angular 6 para crear una PWA mediante la implementación de los principios básicos que hacen una PWA. Comenzaremos creando una aplicación web front-end que consuma una API JSON. Para este asunto, usaremos el módulo Angular HttpClient para enviar solicitudes HTTP a una API JSON estática generada a partir del repositorio de GitHub de jerga de JavaScript simplificada. También usaremos Material Design para crear la interfaz de usuario a través del paquete Angular Material.

A continuación, usaremos el panel "Auditorías" (Lighthouse) de Chrome DevTools para analizar nuestra aplicación web con respecto a los principios básicos de las PWA. Finalmente, explicaremos y agregaremos las funciones de PWA a nuestra aplicación web de acuerdo con la sección "Aplicación web progresiva" en el informe Lighthouse.

Antes de comenzar a implementar nuestra PWA, primero presentemos las PWA y Lighthouse.

Lectura recomendada : Nativo y PWA: ¡Opciones, no desafíos!

¿Qué es una PWA?

Una aplicación web progresiva o PWA es una aplicación web que tiene un conjunto de capacidades (similares a las aplicaciones nativas) que brindan a los usuarios una experiencia similar a la de una aplicación. Las PWA deben cumplir con un conjunto de requisitos esenciales que veremos a continuación. Las PWA son similares a las aplicaciones nativas, pero se implementan y se puede acceder a ellas desde servidores web a través de direcciones URL, por lo que no es necesario pasar por las tiendas de aplicaciones.

Una PWA debe ser:

  • Progresivo
    Trabaja para todos los usuarios, independientemente de la elección del navegador, porque están construidos con mejoras progresivas como principio fundamental.
  • Sensible
    Se adapta a cualquier factor de forma, computadora de escritorio, dispositivo móvil, tableta o lo que sea que se presente.
  • Conectividad independiente
    Mejorado con trabajadores de servicio para trabajar sin conexión o en redes de baja calidad.
  • similar a una aplicación
    Use el modelo de shell de la aplicación para proporcionar navegación e interacciones al estilo de la aplicación.
  • Nuevo
    Siempre actualizado gracias al proceso de actualización del trabajador de servicio.
  • A salvo
    Servido a través de HTTPS para evitar la intromisión y garantizar que el contenido no haya sido manipulado.
  • Visible
    Son identificables como "aplicaciones" gracias a los manifiestos W3C y al ámbito de registro de los trabajadores de servicios, lo que permite que los motores de búsqueda las encuentren.
  • Reconectable
    Facilite el reenganche a través de funciones como notificaciones automáticas.
  • Instalable
    Permita que los usuarios "mantengan" las aplicaciones que les resulten más útiles en su pantalla de inicio sin las molestias de una tienda de aplicaciones.
  • Enlazable
    Comparta fácilmente a través de URL y no requiera una instalación compleja.
¡Más después del salto! Continúe leyendo a continuación ↓

Presentamos el faro

Lighthouse es una herramienta de auditoría de código abierto creada por Google que se puede utilizar para auditar sitios web y aplicaciones en cuanto a rendimiento de accesibilidad, SEO, mejores prácticas y características de PWA.

Puede acceder a Lighthouse desde la pestaña Auditoría en Chrome DevTools como un módulo en Node.js o como una herramienta CLI. Puede usar Lighthouse proporcionando una URL y luego ejecutando las auditorías que le proporcionarán un informe que contiene los resultados de la auditoría, que son básicamente sugerencias sobre cómo puede mejorar su aplicación web.

Instalación de Angular CLI v6 y generación de un proyecto

En esta sección, instalaremos la última versión de Angular CLI y luego la usaremos para crear un nuevo proyecto de Angular 6.

Angular CLI requiere Node.js> = 8.9+ , así que primero asegúrese de tener instalada la versión requerida ejecutando el siguiente comando:

 $ node -v 
Versión de Node.js
Comprobación de la versión del nodo. (Vista previa grande)

En caso de que no tenga Node.js instalado, simplemente puede dirigirse a la página oficial de descarga de Node y obtener los archivos binarios de Node para su sistema.

Ahora, puede continuar e instalar la última versión de Angular CLI ejecutando:

 $ npm install -g @angular/cli

Nota : según la configuración de npm, es posible que deba agregar _sudo_ para instalar paquetes globalmente.

Puede generar su proyecto Angular 6 ejecutando el siguiente comando en su terminal:

 $ ng new pwademo

Esto creará un proyecto con una estructura que se parece a:

Estructura de proyecto angular
Estructura angular del proyecto. (Vista previa grande)

La mayor parte del trabajo realizado estará dentro de la carpeta src/ que contiene el código fuente de la aplicación.

Crear la aplicación angular

Después de generar un proyecto, crearemos una aplicación web que consuma una API JSON y muestre los elementos en la página de inicio. Usaremos el servicio HttpClient para enviar solicitudes HTTP y material angular para construir la interfaz de usuario.

Adición de material angular

Gracias a Angular CLI v6 y al nuevo comando ng add , agregar material angular a su proyecto está a solo un comando de distancia. Solo necesitas ejecutar el siguiente comando desde tu terminal:

 $ cd pwademo $ ng add @angular/material 
Adición de material angular
Adición de material angular. (Vista previa grande)

Puede ver en la captura de pantalla que el comando instala el paquete requerido de npm y actualiza un montón de archivos para configurar Angular Material en su proyecto que anteriormente necesitaba actualizaciones manuales.

Configuración HttpClient y consumo de la API JSON

Ahora, configuremos el proyecto Angular para usar HttpClient para enviar solicitudes HTTP. Primero, debe importar el módulo HttpClientModule en el módulo principal de la aplicación en el archivo src/app/app.module.ts :

 /*...*/ import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Eso es todo. Ahora podemos inyectar y usar HttpClient en cualquier componente o servicio que pertenezca al módulo principal.

Para fines de demostración, consumiremos una API JSON generada estáticamente desde el repositorio de GitHub de jerga de JavaScript simplificada . Si está consumiendo cualquier otro recurso, asegúrese de tener CORS habilitado para que el navegador no rechace la lectura del recurso remoto debido a la Política del mismo origen .

Vamos a crear un servicio que interactúe con la API. Dentro de la carpeta de su proyecto, ejecute:

 $ ng g service api

Esto creará un servicio llamado ApiService en el archivo src/app/api.service.ts .

Ahora abra el archivo src/app/api.service.ts y actualícelo para reflejar los siguientes cambios:

 import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export interface Item{ name: string; description: string; url: string; html: string; markdown: string; } @Injectable({ providedIn: 'root' }) export class ApiService { private dataURL: string = "https://www.techiediaries.com/api/data.json"; constructor(private httpClient: HttpClient) {} fetch(): Observable<Item[]>{ return <Observable<Item[]>this.httpClient.get(this.dataURL); } }

Primero importamos las clases HttpClient y Observable , luego inyectamos HttpClient en el constructor como httpClient y agregamos un método fetch() que llama al método get() de HttpClient (para enviar una solicitud HTTP GET a nuestro punto final JSON) y devuelve un Observable que podemos suscribirnos más tarde.

También declaramos una interfaz Item que representa un único elemento de los datos JSON devueltos.

A continuación, importe este servicio desde el componente de la aplicación. Abra el archivo src/app/app.component.ts y agregue:

 import { Component, OnInit } from '@angular/core'; import { ApiService } from './api.service'; import { Item } from './api.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit{ title = 'pwademo'; items: Array<Item>; constructor(private apiService: ApiService){ } ngOnInit(){ this.fetchData(); } fetchData(){ this.apiService.fetch().subscribe((data: Array<Item>)=>{ console.log(data); this.items = data; }, (err)=>{ console.log(err); }); } }

Importamos el ApiService que creamos antes y lo inyectamos como apiService , también importamos la clase Item que representa un solo elemento de nuestros datos JSON y declaramos la variable de items de tipo Array<Item> que contendrá los elementos obtenidos.

A continuación, agregamos un método fetchData() que llama a nuestro método fetch() que definimos en el ApiService que devuelve un Observable. Simplemente nos suscribimos a este observable para enviar una solicitud GET a nuestro punto final JSON y obtener los datos de respuesta que finalmente asignamos a la matriz de items .

Llamamos al método fetchData() en el evento de ciclo de vida ngOnInit() para que se llame una vez que se inicialice el componente AppComponent .

Agregar la interfaz de usuario de la aplicación

La interfaz de usuario de nuestra aplicación consistirá en una barra de navegación y el esqueleto de la página que se creará con Angular Material.

Antes de usar un componente de material angular, deberá importar su módulo. Cada componente Material pertenece a su propio módulo.

Abra el archivo src/app/app.module.ts y agregue las siguientes importaciones:

 /*...*/ import { MatToolbarModule } from '@angular/material/toolbar'; import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ AppComponent ], imports: [ /*...*/ MatToolbarModule, MatCardModule, MatButtonModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }

Importamos módulos para los componentes de la barra de herramientas, la tarjeta y el botón y los agregamos a la matriz de importaciones del AppModule .

A continuación, abra el archivo src/app/app.component.html , elimine lo que contiene y agregue:

 <mat-toolbar color="primary"> <mat-toolbar-row> <span>JS-jargon</span> </mat-toolbar-row> </mat-toolbar> <main> <mat-card *ngFor="let item of items"> <mat-card-header> <mat-card-title>{{item.name}}</mat-card-title> </mat-card-header> <mat-card-content> {{item.description}} </mat-card-content> <mat-card-actions> <a mat-raised-button href="{{item.url}}" color="primary">More</a> </mat-card-actions> </mat-card> </main>

Usamos componentes de Material para crear la interfaz de usuario. El componente <mat-toolbar> se usa para crear una barra de herramientas de materiales y el componente <mat-card> se usa para crear una tarjeta de materiales, etc.

Iteramos sobre la matriz de items que se completa con el método fetchData() cuando se inicializa el componente y mostramos los elementos como tarjetas de material. Cada tarjeta contiene el nombre, la descripción y un enlace para obtener más información (el enlace tiene el estilo de un botón Material utilizando la directiva mat-raised-button ).

Esta es una captura de pantalla de la aplicación:

Aplicación de demostración
Aplicación de demostración. (Vista previa grande)

Creación de la aplicación para la producción

Por lo general, al verificar las características de PWA de su aplicación, primero debe compilarla para la producción porque la mayoría de las características de PWA no se agregan en el desarrollo. Por ejemplo, no desea tener trabajadores de servicio y almacenamiento en caché habilitados en el desarrollo, ya que periódicamente deberá actualizar los archivos.

Construyamos la aplicación para producción usando el siguiente comando:

 $ ng build --prod

La compilación de producción estará disponible en la carpeta dist/pwademo . Podemos usar una herramienta como http-server para servirlo.

Primero, instale http-server usando el siguiente comando:

 $ npm i -g http-server

A continuación, puede ejecutarlo con el siguiente comando:

 $ cd dist/pwademo $ http-server -o

La opción -o abrirá automáticamente el navegador predeterminado en su sistema y navegará a la dirección https://127.0.0.1:8080/ donde está disponible nuestra aplicación web.

Analizando la aplicación usando Lighthouse

Analicemos ahora nuestra aplicación usando Lighthouse. Primero, inicie Chrome y visite la dirección de nuestra aplicación https://127.0.0.1:8080/ .

A continuación, abra Herramientas para desarrolladores o presione Ctrl + Shift + I y haga clic en el panel Auditoría .

realizar una auditoria
Realice una auditoría. (Vista previa grande)

Preferiblemente, debe configurar Emulación en Móvil en lugar de Escritorio para emular un entorno móvil. A continuación, haga clic en el botón azul Realizar una auditoría… . Se abrirá un cuadro de diálogo en el que deberá elegir los tipos de auditorías que desea realizar en su aplicación web. Desmarque todos los tipos excepto la aplicación web progresiva y haga clic en el botón Ejecutar auditoría .

Auditorías progresivas de aplicaciones web
Auditorías progresivas de aplicaciones web. (Vista previa grande)

Espere a que Lighthouse genere el informe. Esta es una captura de pantalla del resultado en esta etapa:

Informe inicial de PWA
Reporte inicial. (Vista previa grande)

Lighthouse realiza una serie de comprobaciones que validan los aspectos de una aplicación web progresiva especificados por la lista de comprobación de PWA. Obtenemos una puntuación inicial de 36100 que se debe a que pasamos algunas auditorías.

Nuestra aplicación tiene 7 auditorías fallidas principalmente relacionadas con Service Workers , Progressive Enhancement , HTTPS y Web App Manifest , que son los aspectos centrales de una PWA.

Registro de un trabajador de servicio

Las dos primeras auditorías fallidas ("No registra un service worker" y "No responde con un 200 cuando está desconectado") están relacionadas con Service Workers y el almacenamiento en caché. Entonces, ¿qué es un trabajador de servicios?

Un trabajador de servicio es una función que está disponible en los navegadores modernos que se puede usar como un proxy de red que permite que su aplicación intercepte solicitudes de red para almacenar en caché activos y datos. Esto podría usarse para implementar funciones de PWA, como soporte fuera de línea y notificaciones Push, etc.

Para pasar estas auditorías, simplemente necesitamos registrar un trabajador de servicio y usarlo para almacenar archivos en caché localmente. Cuando está fuera de línea, el software debe devolver la versión del archivo en caché local. Veremos un poco más adelante cómo agregar eso con un comando CLI.

Lectura recomendada : Hacer un trabajador de servicios: un estudio de caso

Mejora progresiva

La tercera auditoría fallida ("No proporciona contenido alternativo cuando JavaScript no está disponible") está relacionada con la mejora progresiva , que es un aspecto esencial de una PWA y simplemente se refiere a la capacidad de las PWA para ejecutarse en diferentes navegadores, pero proporciona características avanzadas si están disponibles. Un ejemplo simple de PE es el uso de la etiqueta HTML <noscript> que informa a los usuarios de la necesidad de habilitar JavaScript para ejecutar la aplicación en caso de que no esté habilitado:

 <noscript> Please enable JavaScript to run this application. </noscript>

HTTPS

La cuarta auditoría fallida ("No redirige el tráfico HTTP a HTTPS") está relacionada con HTTPS, que también es un aspecto central de las PWA (los trabajadores de servicio solo pueden ser atendidos desde orígenes seguros, excepto localhost). La auditoría "Usa HTTPS" en sí misma se considera aprobada por Lighthouse, ya que estamos auditando el host local, pero una vez que usa un host real, necesita un certificado SSL. Puede obtener un certificado SSL gratuito de diferentes servicios como Let's Encrypt, Cloudflare, Firebase o Netlify, etc.

El manifiesto de la aplicación web

Las tres auditorías fallidas ("No se le pedirá al usuario que instale la aplicación web", "No está configurado para una pantalla de inicio personalizada" y "La barra de direcciones no coincide con los colores de la marca") están relacionadas con un Manifiesto de aplicación web faltante, que es un archivo en formato JSON que proporciona el nombre, descripción, íconos y otra información requerida por una PWA. Permite a los usuarios instalar la aplicación web en la pantalla de inicio al igual que las aplicaciones nativas sin pasar por una tienda de aplicaciones.

Debe proporcionar un manifiesto de aplicación web y hacer referencia a él desde el archivo index.html mediante una etiqueta <link> con la propiedad rel establecida en manifest . Veremos a continuación cómo podemos hacerlo automáticamente con un comando CLI.

Implementación de características de PWA

Angular CLI v6 le permite agregar rápidamente funciones de PWA a una aplicación Angular existente. Puede convertir su aplicación en una PWA simplemente ejecutando el siguiente comando en su terminal desde la raíz del proyecto:

 $ ng add @angular/pwa

El comando agrega automáticamente funciones de PWA a nuestra aplicación Angular, como:

  • Un archivo manifest.json ,
  • Diferentes tamaños de iconos en la carpeta src/assets/icons ,
  • El trabajador de servicio ngsw-worker.js .

Abra la carpeta dist/ que contiene la compilación de producción. Encontrará varios archivos, pero concentrémonos en los archivos relacionados con las funciones de PWA que mencionamos anteriormente:

Se agregó un archivo manifest.json con el siguiente contenido:

 { "name": "pwademo", "short_name": "pwademo", "theme_color": "#1976d2", "background_color": "#fafafa", "display": "standalone", "scope": "/", "start_url": "/", "icons": [ { "src": "assets/icons/icon-72x72.png", "sizes": "72x72", "type": "image/png" }, { "src": "assets/icons/icon-96x96.png", "sizes": "96x96", "type": "image/png" }, { "src": "assets/icons/icon-128x128.png", "sizes": "128x128", "type": "image/png" }, { "src": "assets/icons/icon-144x144.png", "sizes": "144x144", "type": "image/png" }, { "src": "assets/icons/icon-152x152.png", "sizes": "152x152", "type": "image/png" }, { "src": "assets/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "assets/icons/icon-384x384.png", "sizes": "384x384", "type": "image/png" }, { "src": "assets/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" } ] }

Como puede ver, el archivo manifest.json agregado tiene toda la información requerida por un PWA, como el nombre, la descripción y start_url , etc.

Estructura de proyecto angular
Estructura angular del proyecto. (Vista previa grande)

El archivo manifest.json , enlaces a iconos con diferentes tamaños, que también se agregaron automáticamente en la carpeta de assets/icons . Por supuesto, deberá cambiar esos íconos por los suyos una vez que esté listo para construir la versión final de su PWA.

Estructura de proyecto angular
Estructura angular del proyecto. (Vista previa grande)

En el archivo index.html , se hace referencia al archivo manifest.json mediante:

 <link rel="manifest" href="manifest.json">

El archivo ngsw-worker.js también se agregó automáticamente, que contiene el trabajador del servicio. El código para instalar este service worker se inserta automáticamente en el archivo src/app/app.module.ts :

 ... import { ServiceWorkerModule } from '@angular/service-worker'; @NgModule({ declarations: [ AppComponent ], imports: [ ... ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) ],

@angular/service-worker se instala con el comando ng add y se agrega como una dependencia a pwademo/package.json :

 "dependencies": { ... "@angular/service-worker": "^6.1.0" }

La compatibilidad con la compilación del trabajador del servicio también está habilitada en la CLI. En el archivo angular.json se agrega una opción de configuración "serviceWorker": true .

En el archivo index.html se agrega una metaetiqueta para theme-color con un valor de #1976d2 (también corresponde al valor de theme_color en el archivo manifest.json ):

 <meta name="theme-color" content="#1976d2">

El color del tema le dice al navegador de qué color debe teñir los elementos de la interfaz de usuario, como la barra de direcciones.

Al agregar el color del tema a los archivos index.html y manifest.json , se corrige la auditoría de colores de la marca de coincidencias de la barra de direcciones.

El archivo de configuración del trabajador del servicio

Se agrega otro archivo src/ngsw-config.json al proyecto, pero no es un archivo obligatorio para las PWA. Es un archivo de configuración que le permite especificar qué archivos y URL de datos debe almacenar en caché el trabajador del servicio Angular y cómo debe actualizar los archivos y datos almacenados en caché. Puede encontrar todos los detalles sobre este archivo en los documentos oficiales.

Nota : Al momento de escribir este artículo, con el último comando 6.1.3 anterior ng add @angular/pwa fallará con este error: la Path “/ngsw-config.json” already exists , por lo que por ahora la solución es degradar @angular/cli y @angular/pwa a la versión 6.0.8 .

Simplemente ejecute los siguientes comandos en su proyecto:

 $ npm i @angular/[email protected] $ ng i @angular/[email protected] $ ng add @angular/pwa

Ahora volvamos a ejecutar las auditorías en nuestra PWA local alojada localmente. Esta es la nueva puntuación de PWA:

Informe inicial de PWA
Informe PWA. (Vista previa grande)

La CLI de Angular no agrega automáticamente el código alternativo de JavaScript que mencionamos en la sección Mejora progresiva, así que abra el archivo src/index.html y agréguelo:

 <noscript> Please enable JavaScript to run this application. </noscript>

A continuación, reconstruya su aplicación y vuelva a ejecutar las auditorías. Este es el resultado ahora:

Informe inicial de PWA
Informe PWA. (Vista previa grande)

Solo tenemos una auditoría fallida que está relacionada con la redirección de HTTPS. Necesitamos alojar la aplicación y configurar la redirección de HTTP a HTTPS.

Ahora ejecutemos las auditorías en una versión alojada y segura de nuestra PWA.

Informe final de PWA
Informe final de la PWA. (Vista previa grande)

Obtenemos una puntuación de 100100 , lo que significa que hemos implementado con éxito todos los principios básicos de las PWA.

Puede obtener el código final de esta PWA de demostración en este repositorio de GitHub.

Conclusión

En este tutorial, creamos una aplicación Angular simple y la convertimos en una PWA mediante la CLI de Angular. Utilizamos Lighthouse de Google para auditar nuestra aplicación en busca de funciones de PWA y explicamos varios principios básicos de PWA, como Service Workers, para agregar soporte fuera de línea y notificaciones automáticas. El archivo Web Manifest para habilitar funciones de agregar a la pantalla de inicio y pantalla de inicio, Mejora progresiva y HTTPS .

Es posible que también deba verificar manualmente otros elementos resaltados (en la sección "Elementos adicionales para verificar manualmente") pero que Lighthouse no verificó automáticamente. Estas verificaciones son requeridas por la lista de verificación de PWA de referencia de Google. No afectan la puntuación de PWA, pero es importante que los verifique manualmente. Por ejemplo, debe asegurarse de que su sitio funcione en todos los navegadores y que cada página tenga una URL que sea importante para poder compartirla en las redes sociales.

Dado que las PWA también tienen que ver con otros aspectos, como una mejor percepción del rendimiento y la accesibilidad, también puede usar Lighthouse para auditar su PWA (o cualquier sitio web en general) para estos aspectos y mejorarlo según sea necesario.