Esegui il pre-rendering delle route con responsive-snap

Non utilizzi il rendering lato server, ma vuoi comunque velocizzare le prestazioni del tuo sito React? Prova il pre-rendering.

react-snap è una libreria di terze parti che esegue il pre-rendering delle pagine del tuo sito in file HTML statici. In questo modo, puoi migliorare i tempi di prima visualizzazione nella tua applicazione.

Ecco un confronto della stessa applicazione con e senza pre-rendering caricato su una connessione 3G simulata e un dispositivo mobile:

Un confronto fianco a fianco del caricamento. La versione che utilizza il pre-rendering carica 4,2 secondi più velocemente.

Perché è utile?

Il principale problema di prestazioni delle applicazioni a pagina singola di grandi dimensioni è che l'utente deve attendere il completamento del download dei bundle JavaScript che compongono il sito prima di poter vedere i contenuti effettivi. Più grandi sono i pacchetti, più tempo dovrà attendere l'utente.

Per risolvere il problema, molti sviluppatori adottano l'approccio di eseguire il rendering dell'applicazione sul server anziché avviarla solo nel browser. Con ogni transizione di pagina/percorso, il codice HTML completo viene generato sul server e inviato al browser, il che riduce i tempi di First Paint, ma a un costo di un tempo di risposta più lento.

Il pre-rendering è una tecnica separata meno complessa del rendering lato server, ma offre anche un modo per migliorare i tempi di prima visualizzazione nell'applicazione. Un browser headless, ovvero un browser senza interfaccia utente, viene utilizzato per generare file HTML statici di ogni percorso durante la fase di compilazione. Questi file possono quindi essere inviati insieme ai bundle JavaScript necessari per l'applicazione.

react-snap

react-snap utilizza Puppeteer per creare file HTML pre-renderizzati di percorsi diversi nella tua applicazione. Per iniziare, installalo come dipendenza di sviluppo:

npm install --save-dev react-snap

Quindi aggiungi uno script postbuild in package.json:

"scripts": {
  //...
  "postbuild": "react-snap"
}

In questo modo, il comando react-snap verrà eseguito automaticamente ogni volta che viene eseguita una nuova compilazione delle applicazioni (npm build).

L'ultima cosa che dovrai fare è modificare il modo in cui l'applicazione viene avviata. Modifica il file src/index.js come segue:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}

Anziché utilizzare solo ReactDOM.render per eseguire il rendering dell'elemento React principale direttamente nel DOM, viene controllato se sono già presenti nodi secondari per determinare se i contenuti HTML sono stati pre-renderizzati (o visualizzati sul server). In questo caso, viene utilizzato ReactDOM.hydrate per collegare gli ascoltatori di eventi all'HTML già creato anziché crearlo di nuovo.

La compilazione dell'applicazione ora genererà file HTML statici come payload per ogni percorso sottoposto a scansione. Puoi dare un'occhiata all'aspetto del payload HTML facendo clic sull'URL della richiesta HTML e poi sulla scheda Anteprime in Chrome DevTools.

Un confronto prima e dopo. Lo scatto successivo mostra che i contenuti sono stati visualizzati.

Lampo di contenuti senza stile

Sebbene il codice HTML statico venga ora visualizzato quasi immediatamente, rimane senza stile per impostazione predefinita, il che potrebbe causare il problema di visualizzazione di un "lampo di contenuti senza stile" (FOUC). Questo può essere particolarmente evidente se utilizzi una libreria CSS-in-JS per generare i selettori, poiché il bundle JavaScript dovrà terminare l'esecuzione prima che sia possibile applicare gli stili.

Per evitare che ciò accada, il CSS critico, ovvero la quantità minima di CSS necessaria per il rendering della pagina iniziale, può essere inserito direttamente nel <head> del documento HTML. react-snap utilizza un'altra libreria di terze parti, minimalcss, per estrarre eventuali CSS critici per percorsi diversi. Per attivare questa opzione, specifica quanto segue nel file package.json:

"reactSnap": {
  "inlineCss": true
}

Se dai un'occhiata all'anteprima della risposta in Chrome DevTools, ora viene visualizzata la pagina con stile e CSS critico in linea.

Un confronto prima e dopo. La foto dopo mostra che i contenuti sono stati visualizzati e hanno uno stile grazie al CSS critico in linea.

Conclusione

Se non esegui il rendering lato server dei percorsi nella tua applicazione, utilizza react-snap per eseguire il pre-rendering dell'HTML statico per gli utenti.

  1. Installalo come dipendenza per lo sviluppo e inizia solo con le impostazioni predefinite.
  2. Utilizza l'opzione sperimentale inlineCss per incorporare il CSS fondamentale se funziona per il tuo sito.
  3. Se utilizzi la suddivisione del codice a livello di componente all'interno di qualsiasi route, fai attenzione a non eseguire il pre-rendering di uno stato di caricamento per gli utenti. Il react-snap README tratta questo argomento in modo più dettagliato.