Progressive Web Apps con Angular - Yessica54/carrera-front-end GitHub Wiki
Una Progressive Web App o PWA aúna lo mejor de una página web y de una aplicación nativa, ofreciendo grandes beneficios tanto al usuario como al dueño del sitio web. Su versatilidad y naturaleza progresiva aseguran una experiencia móvil perfecta desde cualquier dispositivo y sistema operativo.
55% de usuarios abandona un sitio si este no carga en 3 segundos La mayoria de sitios tarad 19 segundos en cargar Sitios que cargan dentro de los 5segundos aumentan su objetivo
La mayoría de nuestros usuarios consumen el contenido en mobile, Sin embargo la retención es mayor en Apps
- Funciona Offline
- Speed ( Uso de cache)
- Push Notifications
- Web Based
- Deep Links ( Open App Using link) is easy to use in web, already use url/
- Small bundle.
- Easy to release and update.
- Desktop Icon
Un service worker es una secuencia de comandos que tu navegador ejecuta en segundo plano, separado de una página web, abriéndoles la puerta a funciones que no necesitan una página web ni interacción de usuario.
ng add @angular/pwa
Es una herramienta de auditoria para pwa
Para los assest caché hay dos forma de instalacion o actualizacion, esto se hace en el archivo de configuración ngsw-config.json
- lazy: a medida que el usuario va necesitando lso assest va cargandolos en cache
- prefetch: Toma todos los archivos assests y lo guarda en cache de una vez.
Al igual que los caches de los assets en el archivo de configuración ngsw-config.json, se debe agregar la configuración para para las API, ejemplo de esto:
"dataGroups": [ { "name": "api", "urls": ["https://platzi-store.herokuapp.com/**"], "cacheConfig": { "maxSize": 3, --> numeros de request que guarda "maxAge": "5m", --> Timpo de guarda cache "strategy": "freshness",--> freshness: si no puede ir a internet lo trae de cache, performance: si esta en cache lo trae "timeout": "2s" --> tiempo de espera } } ]
Se utiliza la clase https://angular.io/api/service-worker/SwUpdate ejemplo
import { SwUpdate } from '@angular/service-worker';
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor(
private swUpdate: SwUpdate,
) {
}
ngOnInit() {
this.updatePWA();
}
updatePWA() {
this.swUpdate.available
.subscribe(value => {
console.log('update:', value);
window.location.reload();
});
}
}
Se debe incluir los modulos de angularFire para incluir las notificaciones push
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFireStorageModule } from '@angular/fire/storage';
import { AngularFireMessagingModule } from '@angular/fire/messaging';
import { AngularFirestoreModule } from '@angular/fire/firestore';
@NgModule({
declarations: [
AppComponent,
LayoutComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
SharedModule,
CoreModule,
BrowserAnimationsModule,
HttpClientModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFireStorageModule,
AngularFireMessagingModule,
AngularFirestoreModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
],
providers: [],
bootstrap: [AppComponent]
Es necesario obtener los permisos del usuario y se realiza una solicitud de token, se debe crear un método que escuche la notificacion
import { Component, HostListener, OnInit } from '@angular/core';
import { AngularFireMessaging } from '@angular/fire/messaging';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
interface Token {
token: string;
}
@Component({
selector: 'app-root',
template: '<router-outlet></router-outlet>',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
private tokensCollections: AngularFirestoreCollection<Token>;
constructor(
private messaging: AngularFireMessaging,
private database: AngularFirestore
) {
this.tokensCollections = this.database.collection<Token>('tokens');
}
ngOnInit() {
this.requestPermission();
}
requestPermission() {
this.messaging.requestToken
.subscribe(token => {
console.log(token);
this.tokensCollections.add({token});
});
}
listenNotifications() {
this.messaging.messages
.subscribe(message => {
console.log(message);
});
}
}
Se debe agregar las configuraciones de las notificaciones de push de firebase
export const environment = {
production: false,
url_api: 'https://platzi-store.herokuapp.com',
firebase: {
apiKey: 'AIzaSyCehjKaeCl1j35pAId6TId-L2YdBQqKvSI',
authDomain: 'angular-pwa-platzi.firebaseapp.com',
databaseURL: 'https://angular-pwa-platzi.firebaseio.com',
projectId: 'angular-pwa-platzi',
storageBucket: 'angular-pwa-platzi.appspot.com',
messagingSenderId: '1011695246249',
appId: '1:1011695246249:web:1f9c4802a5cdff9c8842b8'
}
};
Se debe crear el archivo firebase-messaging-sw.js dentro de src con el siguiente contenido
// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here, other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/7.6.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.6.0/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
apiKey: "AIzaSyC5VMt0DoEcDA_RNaQXX1wUpc0yKg2G_z4",
authDomain: "newtp-200719.firebaseapp.com",
databaseURL: "https://newtp-200719.firebaseio.com",
projectId: "newtp-200719",
storageBucket: "newtp-200719.appspot.com",
messagingSenderId: "359003727463",
appId: "1:359003727463:web:cb1c8b960eb185658696c2"
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
Adiccionalmente agregar en angular.json a la compilación en assets
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest",
"src/firebase-messaging-sw.js"
],
Se instala el paquete npm install -g lighthouse
, para la configuracion basica se ejecuta el comando lighthouse url
, para la resto de la configuración ver la documentacion