Esegui il pre-rendering delle route con responsive-snap

Non hai il rendering lato server, ma vuoi comunque velocizzare le prestazioni del tuo sito React? Prova il prerendering.

react-snap è una libreria di terze parti che esegue il prerendering 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 problema di prestazioni principale delle applicazioni di grandi dimensioni a pagina singola è che l'utente deve attendere il completamento del download dei bundle JavaScript che compongono il sito prima di poter visualizzare i contenuti reali. Più sono grandi i bundle, più a lungo l'utente dovrà attendere.

Per risolvere il problema, molti sviluppatori adottano l'approccio di eseguire il rendering dell'applicazione sul server anziché avviarla solo nel browser. A ogni transizione di pagina/route, il codice HTML completo viene generato sul server e inviato al browser. In questo modo vengono ridotti i tempi di First Paint, ma ciò comporta un rallentamento del Time to First Byte.

Il pre-rendering è una tecnica separata e meno complessa del rendering server, ma consente anche di migliorare i tempi di First Paint nella tua applicazione. Viene utilizzato un browser headless o senza interfaccia utente per generare file HTML statici di ogni route durante il tempo di creazione. Questi file possono quindi essere spediti insieme ai bundle JavaScript necessari per l'applicazione.

react-snap

react-snap utilizza Puppeteer per creare file HTML prerenderizzati di diverse route 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. Per verificare l'aspetto del payload HTML, fai clic sull'URL della richiesta HTML e quindi 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). Ciò può essere notato in particolare se utilizzi una libreria CSS-in-JS per generare selettori, poiché il bundle JavaScript dovrà terminare l'esecuzione prima di poter applicare qualsiasi stile.

Per evitare questo problema, 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. Puoi attivare questa funzionalità specificando 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.