Per progettare un'applicazione in modo da sfruttare al meglio la tecnologia che rende le PWA affidabili, installabili e capaci, devi comprendere l'applicazione e i suoi vincoli e scegliere un'architettura appropriata per entrambe.
SPA e MPA
Attualmente, nello sviluppo web esistono due pattern di architettura principali: app su singola pagina (SPA) e app multipagina (MPA).
Le app a pagina singola sono definite dal fatto che JavaScript lato client controlla la maggior parte o tutto il rendering HTML di una pagina in base ai dati recuperati o forniti all'app. L'app sostituisce la navigazione integrata del browser, sostituendola con le sue funzionalità di routing e gestione delle visualizzazioni.
Le app multipagina di solito hanno HTML pre-renderizzato inviato direttamente al browser, spesso migliorato con JavaScript lato client dopo il caricamento dell'HTML da parte del browser e si basano sui meccanismi di navigazione integrati del browser per visualizzare le visualizzazioni successive.
Entrambe le architetture possono essere utilizzate per creare PWA.
Ognuno di essi presenta vantaggi e svantaggi e la scelta della soluzione giusta per il caso d'uso e il contesto è fondamentale per offrire agli utenti un'esperienza rapida e affidabile.
App a pagina singola
- Aggiornamenti in-page per lo più atomici.
- Dipendenze lato client caricate all'avvio.
- I caricamenti successivi sono rapidi grazie all'utilizzo della cache.
- Costo di caricamento iniziale elevato.
- Le prestazioni dipendono dall'hardware e dalla connessione di rete del dispositivo.
- È richiesta una maggiore complessità dell'app.
Le app a pagina singola sono una buona scelta di architettura se:
- L'interazione utente è incentrata principalmente sugli aggiornamenti atomici di dati interconnessi visualizzati nella stessa pagina, ad esempio una dashboard di dati in tempo reale o un'app di editing video.
- L'applicazione ha dipendenze di inizializzazione solo lato client, ad esempio un provider di autenticazione di terze parti con un costo di avvio proibitivo.
- I dati necessari per il caricamento di una vista si basano su un contesto specifico solo lato client, ad esempio la visualizzazione dei controlli per un componente hardware connesso.
- L'app è abbastanza piccola e semplice da non avere un impatto sui lati negativi elencati sopra.
Le SPA potrebbero non essere una buona scelta di architettura se:
- Le prestazioni del caricamento iniziale sono essenziali. Le APS di solito devono caricare più codice JavaScript per determinare cosa caricare e come visualizzarlo. Il tempo di analisi e di esecuzione di questo codice JavaScript, combinato con il recupero dei contenuti, è più lento rispetto all'invio di HTML sottoposto a rendering.
- La tua app viene eseguita principalmente su dispositivi con un consumo medio-bassa. Poiché le SPA si basano su JavaScript per il rendering, l'esperienza utente dipende in misura molto più significativa dalla potenza del dispositivo specifico rispetto a quanto accade in un'AMP.
Poiché le APS devono sostituire la navigazione integrata del browser con il routing, le APS richiedono un livello minimo di complessità relativo all'aggiornamento efficiente della vista corrente, alla gestione delle modifiche di navigazione e alla pulizia di viste precedenti che altrimenti verrebbero gestite dal browser, rendendole complessivamente più difficili da gestire e pesano maggiormente sul dispositivo dell'utente.
App a più pagine
- Principalmente aggiornamenti a pagina intera.
- La velocità di rendering iniziale è fondamentale.
- Lo scripting lato client può essere un miglioramento.
- Le visualizzazioni secondarie richiedono un'altra chiamata al server.
- Il contesto non viene trasferito da una visualizzazione all'altra.
- Richiede un server o il pre-rendering.
Le app su più pagine sono una buona scelta architetturale se:
- L'interazione degli utenti è incentrata principalmente sulle visualizzazioni di un singolo dato con dati facoltativi basati sul contesto, ad esempio un'app di notizie o di e-commerce.
- La velocità di rendering iniziale è fondamentale, in quanto l'invio di HTML già visualizzato al browser è più veloce rispetto all'assemblaggio da una richiesta di dati dopo il caricamento, l'analisi e l'esecuzione di un'alternativa basata su JavaScript.
- L'interattività o il contesto lato client possono essere inclusi come miglioramento dopo il caricamento iniziale, ad esempio sovrapponendo un profilo a una pagina visualizzata o aggiungendo componenti secondari lato client dipendenti dal contesto.
Gli MPA potrebbero non essere una buona scelta per l'architettura se:
- Il ricaricamento, la nuova analisi e la nuova esecuzione di JavaScript o CSS sono proibitivi. Questo problema è mitigato nelle PWA con i service worker.
- Il contesto lato client, ad esempio la posizione dell'utente, non viene trasferito senza problemi da una visualizzazione all'altra e ottenerlo di nuovo potrebbe essere costoso. Deve essere acquisito e recuperato o richiesto di nuovo tra le visualizzazioni.
Poiché le singole visualizzazioni devono essere visualizzate dinamicamente da un server o pre-visualizzate prima dell'accesso, ciò potrebbe limitare l'hosting o aumentare la complessità dei dati.
Quale scegliere?
Nonostante questi pro e contro, entrambe le architetture sono valide per la creazione della tua PWA. Puoi anche combinarli per parti diverse della tua app, a seconda delle sue esigenze, ad esempio puoi avere schede dello Store che seguono un'architettura MPA e il flusso di pagamento che segue un'architettura SPA.
Indipendentemente dalla scelta, il passaggio successivo è capire come utilizzare al meglio i worker di servizio per offrire la migliore esperienza.
La potenza del Service worker
Il worker del servizio è molto potente oltre il routing di base e la pubblicazione di risposte memorizzate nella cache e di rete. Possiamo creare algoritmi complessi che possono migliorare l'esperienza e il rendimento dell'utente.
Include il service worker (SWI)
Un pattern emergente per l'utilizzo dei service worker come parte integrante dell'architettura di un sito è il servizio worker include (SWI). SWI suddivide i singoli asset, in genere una pagina HTML, in pezzi in base alle esigenze di memorizzazione nella cache, quindi li riunisce nel service worker per migliorare la coerenza, le prestazioni e l'affidabilità, riducendo al contempo le dimensioni della cache.
Questa immagine è una pagina web di esempio. È composta da cinque sezioni diverse che suddividono la pagina in:
- Layout generale.
- Intestazione globale (barra scura in alto).
- Area dei contenuti (linee e immagine a sinistra al centro).
- Barra laterale (barra alta di colore medio scuro in alto a destra).
- Piè di pagina (barra inferiore scura).
Layout generale
È improbabile che il layout complessivo cambi spesso e non ha dipendenze. È un buon candidato per il precaching.
Titolo e piè di pagina
L'intestazione e il piè di pagina globali contengono elementi come il menu superiore e il piè di pagina del sito e presentano una sfida particolare: se la pagina dovesse essere memorizzata nella cache nel suo complesso, questi elementi potrebbero cambiare tra un caricamento e l'altro, a seconda di quando è stata memorizzata nella cache la pagina in questione.
Separandoli e memorizzandoli nella cache indipendentemente dai contenuti, puoi assicurarti che gli utenti ricevano sempre la stessa versione, indipendentemente dal momento in cui vengono memorizzati nella cache. Poiché vengono aggiornati di rado, sono anche buoni candidati per il pre-caching. Hanno però una dipendenza: i file CSS e JavaScript del sito.
CSS e JavaScript
Idealmente, i file CSS e JavaScript del sito dovrebbero essere memorizzati nella cache con una strategia di convalida in caso di dati non aggiornati per consentire aggiornamenti incrementali senza dover aggiornare il service worker, come nel caso degli asset pre-memorizzati nella cache. Devono comunque essere mantenuti alla versione minima ogni volta che il service worker si aggiorna con una nuova intestazione o piè di pagina globale. Per questo motivo, anche la cache deve essere aggiornata con l'ultima versione degli asset quando viene installato il service worker.
Area dei contenuti
Poi c'è l'area dei contenuti. A seconda della frequenza degli aggiornamenti, una buona strategia è "Priorità alla rete" o "Non aggiornato durante la convalida". Le immagini devono essere memorizzate nella cache con una strategia cache first, come discusso in precedenza.
Barra laterale
Infine, presumendo che i contenuti della barra laterale includano contenuti secondari come tag ed elementi correlati, non è abbastanza fondamentale per estrarli dalla rete. In questo caso è utile una strategia di convalida in caso di dati non aggiornati.
Ora, dopo aver letto tutto, potresti pensare che puoi eseguire questo tipo di memorizzazione nella cache per sezione solo per le app a pagina singola. Tuttavia, adottando pattern ispirati agli includendi lato client o agli includendi lato server nel tuo service worker, con alcune funzionalità avanzate del service worker puoi farlo per entrambe le architetture.
Fai una prova
Puoi provare il servizio worker incluso nel prossimo codelab:
Risposte dinamiche
La pagina precedente potrebbe essere creata utilizzando il modello di shell dell'app nel mondo delle SPA, in cui la shell dell'app viene memorizzata nella cache, poi pubblicata e i contenuti vengono caricati sul lato client. Con l'introduzione e l'ampia disponibilità dell'API Streams, sia la shell dell'app sia i contenuti possono essere combinati nel service worker e trasmessi in streaming al browser, offrendo la flessibilità della memorizzazione nella cache della shell dell'app con la velocità delle MPA.
Il motivo è che:
- Gli stream possono essere creati in modo asincrono, consentendo a parti diverse di uno stream di provenire da altre origini.
- L'autore della richiesta di uno stream può iniziare a lavorare sulla risposta non appena è disponibile il primo blocco di dati, invece di attendere il completamento dell'intero elemento.
- I parser ottimizzati per lo streaming, incluso il browser, possono visualizzare progressivamente i contenuti dello stream prima che venga completato, accelerando le prestazioni percepite della risposta.
Grazie a queste tre proprietà degli stream, le architetture basate sullo streaming in genere hanno un rendimento percepito più rapido rispetto a quelle che non lo sono.
L'utilizzo dell'API Streams può essere complicato in quanto è complessa e di basso livello. Fortunatamente, esiste un modulo Workbox che può aiutarti a configurare le risposte in streaming per i tuoi worker di servizio.
Domini, origini e ambito delle PWA
I web worker, inclusi i service worker, lo spazio di archiviazione e persino la finestra di una PWA installata, sono tutti regolati da uno dei meccanismi di sicurezza più critici sul web: il criterio della stessa origine. All'interno della stessa origine, le autorizzazioni vengono concesse, i dati possono essere condivisi e il service worker può comunicare con client diversi. Al di fuori della stessa origine, le autorizzazioni non vengono concesse automaticamente e i dati sono isolati e non accessibili tra origini diverse.
Criterio della stessa origine
Due URL sono definiti come aventi l'origine esatta se il protocollo, la porta e l'host sono gli stessi.
Ad esempio: https://squoosh.app
e https://squoosh.app/v2
hanno la stessa origine, ma http://squoosh.app
, https://squoosh.com
, https://app.squoosh.app
e https://squoosh.app:8080
hanno origini diverse. Per ulteriori informazioni ed esempi, consulta il riferimento MDN per il criterio della stessa origine.
La modifica dei sottodomini non è l'unico modo in cui un host può cambiare. Ogni host è costituito da un dominio di primo livello (TLD), un dominio di secondo livello (SLD) e da zero o più etichette (a volte chiamate sottodomini), separate da punti e lette da destra a sinistra in un URL. Una modifica in uno qualsiasi degli elementi determina un host diverso.
Nel modulo sulla gestione delle finestre, abbiamo già visto l'aspetto del browser in-app quando un utente passa a un'origine diversa da una PWA installata.
Questo browser in-app viene visualizzato anche se i siti web hanno lo stesso TLD e SLD, ma con etichette diverse, in quanto vengono considerati origini diverse.
Uno degli aspetti chiave di un'origine in un contesto di navigazione web è il funzionamento dello spazio di archiviazione e delle autorizzazioni. Un'origine condivide molte funzionalità tra tutti i contenuti e le PWA al suo interno, tra cui:
- Dati e quota di spazio di archiviazione (IndexedDB, cookie, spazio di archiviazione web, spazio di archiviazione della cache).
- Registrazioni dei service worker.
- Autorizzazioni concesse o negate (ad esempio push web, geolocalizzazione, sensori).
- Registrazioni push web.
Quando passi da un'origine a un'altra, l'accesso precedente viene revocato, quindi le autorizzazioni devono essere concesse di nuovo e la PWA non può accedere a tutti i dati salvati nello spazio di archiviazione.