Lato client, lato server e pre-rendering per le app Web

Pubblicato: 2022-03-11

C'è qualcosa che sta succedendo all'interno della comunità front-end di recente. Il rendering lato server sta ottenendo sempre più trazione grazie a React e alla sua funzione di idratazione lato server integrata. Ma non è l'unica soluzione per offrire un'esperienza veloce all'utente con un punteggio TTFB (time-to-first-byte) super veloce: anche il pre-rendering è una strategia piuttosto buona. Qual è la differenza tra queste soluzioni e un'applicazione completamente renderizzata dal client?

Applicazione resa dal cliente

Poiché esistono framework come Angular, Ember.js e Backbone, gli sviluppatori front-end tendono a eseguire il rendering di tutto lato client. Grazie a Google e alla sua capacità di "leggere" JavaScript, funziona abbastanza bene ed è anche SEO friendly.

Con una soluzione di rendering lato client, reindirizzi la richiesta a un singolo file HTML e il server la consegnerà senza alcun contenuto (o con una schermata di caricamento) fino a quando non recuperi tutto il JavaScript e lascia che il browser compili tutto prima di eseguire il rendering del contenuto.

Con una connessione Internet buona e affidabile, è abbastanza veloce e funziona bene. Ma può essere molto meglio, e non deve essere difficile farlo in questo modo. Questo è ciò che vedremo nelle sezioni seguenti.

Rendering lato server (SSR)

Una soluzione SSR è qualcosa che facevamo molto, molti anni fa, ma tendiamo a dimenticare a favore di una soluzione di rendering lato client.

Con le vecchie soluzioni di rendering lato server, creavi una pagina Web, ad esempio con PHP, il server compilava tutto, includeva i dati e consegnava al client una pagina HTML completamente popolata. È stato veloce ed efficace.

Ma... ogni volta che passavi a un altro percorso, il server doveva rifare il lavoro da capo: ottenere il file PHP, compilarlo e consegnare l'HTML, con tutti i CSS e JS che ritardavano il caricamento della pagina a poche centinaia di ms o anche interi secondi.

E se potessi caricare la prima pagina con la soluzione SSR e quindi utilizzare un framework per eseguire il routing dinamico con AJAX, recuperando solo i dati necessari?

Questo è il motivo per cui SSR sta ottenendo sempre più trazione all'interno della comunità perché React ha reso popolare questo problema con una soluzione facile da usare: il metodo RenderToString .

Questo nuovo tipo di applicazione web è chiamato app universale o app isomorfa . C'è ancora qualche controversia sui significati esatti di questi termini e sulla relazione tra loro, ma molte persone li usano in modo intercambiabile.

Ad ogni modo, il vantaggio di questa soluzione è la possibilità di sviluppare un'app lato server e lato client con lo stesso codice e offrire all'utente un'esperienza davvero veloce con dati personalizzati. Lo svantaggio è che è necessario eseguire un server.

SSR viene utilizzato per recuperare i dati e precompilare una pagina con contenuti personalizzati, sfruttando l'affidabile connessione Internet del server. Cioè, la connessione Internet del server è migliore di quella di un utente con lie-fi), quindi è in grado di precaricare e amalgamare i dati prima di consegnarli all'utente.

Con i dati precompilati, l'utilizzo di un'app SSR può anche risolvere un problema che le app renderizzate dal client hanno con la condivisione social e il sistema OpenGraph. Ad esempio, se hai un solo file index.html da consegnare al cliente, avrà solo un tipo di metadati, molto probabilmente i metadati della tua home page. Questo non verrà contestualizzato quando desideri condividere un percorso diverso, quindi nessuno dei tuoi percorsi verrà mostrato su altri siti con il proprio contenuto utente (descrizione e immagine di anteprima) che gli utenti vorrebbero condividere con il mondo.

Pre-rendering

Il server obbligatorio per un'app universale può essere un deterrente per alcuni e potrebbe essere eccessivo per una piccola applicazione. Questo è il motivo per cui il pre-rendering può essere davvero un'ottima alternativa.

Ho scoperto questa soluzione con Preact e la sua CLI che ti consente di compilare tutti i percorsi preselezionati in modo da poter archiviare un file HTML completamente popolato su un server statico . Ciò ti consente di offrire un'esperienza super veloce all'utente, grazie alla funzione di idratazione Preact/React, senza la necessità di Node.js.

Il problema è che, poiché questo non è SSR, non hai dati specifici dell'utente da mostrare a questo punto: è solo un file statico (e alquanto generico) inviato direttamente alla prima richiesta, così com'è. Quindi, se disponi di dati specifici dell'utente, qui è dove puoi integrare uno scheletro ben progettato per mostrare all'utente che i loro dati stanno arrivando, per evitare qualche frustrazione da parte loro:

Utilizzo di uno scheletro del documento come parte di un indicatore di caricamento

C'è un altro problema: affinché questa tecnica funzioni, è comunque necessario disporre di un proxy o qualcosa per reindirizzare l'utente al file corretto.

Come mai?

Con un'applicazione a pagina singola, devi reindirizzare tutte le richieste al file radice, quindi il framework reindirizza l'utente con il suo sistema di routing integrato. Quindi il caricamento della prima pagina è sempre lo stesso file radice.

Affinché una soluzione di pre-rendering funzioni, devi comunicare al tuo proxy che alcuni percorsi richiedono file specifici e non sempre il file index.html radice.

Ad esempio, supponiamo di avere quattro percorsi ( / , /about , /jobs e blog ) e tutti hanno layout diversi. Hai bisogno di quattro diversi file HTML per fornire lo scheletro all'utente che lascerà quindi React/Preact/etc. reidratarlo con i dati. Quindi, se reindirizzi tutti quei percorsi al file index.html radice, la pagina avrà una sensazione spiacevole e glitch durante il caricamento, per cui l'utente vedrà lo scheletro della pagina sbagliata fino al termine del caricamento e alla sostituzione del layout. Ad esempio, l'utente potrebbe vedere uno scheletro della home page con una sola colonna, quando ha chiesto una pagina diversa con una galleria simile a Pinterest.

La soluzione è dire al tuo proxy che ognuno di questi quattro percorsi ha bisogno di un file specifico:

  • https://my-website.com → Reindirizza al file index.html radice
  • https://my-website.com/about → Reindirizzamento al file /about/index.html
  • https://my-website.com/jobs → Reindirizzamento al file /jobs/index.html
  • https://my-website.com/blog → Reindirizzamento al file /blog/index.html

Questo è il motivo per cui questa soluzione può essere utile per piccole applicazioni: puoi vedere quanto sarebbe doloroso se avessi poche centinaia di pagine.

A rigor di termini, non è obbligatorio farlo in questo modo: potresti semplicemente usare direttamente un file statico. Ad esempio, https://my-website.com/about/ funzionerà senza alcun reindirizzamento perché cercherà automaticamente un index.html all'interno della sua directory. Ma hai bisogno di questo proxy se hai URL param: https://my-website.com/profile/guillaume dovrà reindirizzare la richiesta a /profile/index.html con il suo layout, perché profile/guillaume/index.html non esiste e attiverà un errore 404.

Un diagramma di flusso che mostra come un proxy fa la differenza in una soluzione di pre-rendering, come descritto nel paragrafo precedente


In breve, ci sono tre viste di base in gioco con le strategie di rendering sopra descritte: una schermata di caricamento, uno scheletro e l'intera pagina una volta che è stata finalmente renderizzata.

Confrontando una schermata di caricamento, uno scheletro e una pagina completamente renderizzata

A seconda della strategia, a volte utilizziamo tutte e tre queste viste ea volte passiamo direttamente a una pagina con rendering completo. Solo in un caso d'uso siamo costretti a utilizzare un approccio diverso:

Metodo Atterraggio (es / ) Statico (es /about ) Dinamica fissa (es /news ) Dinamica parametrizzata (es /users/:user-id )
Rendering dal cliente Caricamento → Completo Caricamento → Completo Caricamento → Scheletro → Completo Caricamento → Scheletro → Completo
Pre-renderizzato Completo Completo Scheletro → Completo HTTP 404 (pagina non trovata)
Pre-renderizzato con proxy Completo Completo Scheletro → Completo Scheletro → Completo
SSR Completo Completo Completo Completo

Il rendering solo client spesso non è sufficiente

Le applicazioni renderizzate dal client sono qualcosa che dovremmo evitare ora perché possiamo fare di meglio per l'utente. E fare meglio, in questo caso, è facile come la soluzione di pre-rendering. È sicuramente un miglioramento rispetto al rendering solo client e più facile da implementare rispetto a un'applicazione con rendering completamente lato server.

Un'applicazione SSR/universale può essere davvero potente se si dispone di un'applicazione di grandi dimensioni con molte pagine diverse. Consente ai tuoi contenuti di essere focalizzati e pertinenti quando parli con un social crawler. Questo vale anche per i robot dei motori di ricerca, che ora tengono conto delle prestazioni del tuo sito quando lo classifica.

Resta sintonizzato per un tutorial di follow-up, in cui illustrerò la trasformazione di una SPA in versioni pre-renderizzate e SSR e confronterò le loro prestazioni.

Correlati: Panoramica dei più diffusi generatori di siti statici