ReactJS rendering lato server vs rendering lato client


120

Ho appena iniziato a studiare ReactJS e ho scoperto che ti offre 2 modi per eseguire il rendering delle pagine: lato server e lato client. Ma non riesco a capire come usarlo insieme. Sono 2 modi separati per creare l'applicazione o possono essere usati insieme?

Se possiamo usarlo insieme, come farlo: dobbiamo duplicare gli stessi elementi sul lato server e sul lato client? Oppure, possiamo semplicemente costruire le parti statiche della nostra applicazione sul server e le parti dinamiche sul lato client, senza alcuna connessione al lato server che era già pre-renderizzato?


1
Risposta breve, NO: puoi disaccoppiare, inviare html statico e modificarlo completamente nel rendering client. Ho aggiunto dettagli nella mia risposta.
Kira

Risposte:


108

Per un dato sito web / web-applicazione, è possibile utilizzare reagire sia sul lato client , server-side o di entrambi .

Dalla parte del cliente

Qui, stai eseguendo completamente ReactJS sul browser. Questa è la configurazione più semplice e include la maggior parte degli esempi (inclusi quelli su http://reactjs.org ). L'HTML iniziale visualizzato dal server è un segnaposto e l'intera interfaccia utente viene visualizzata nel browser una volta caricati tutti gli script.

Lato server

Pensa a ReactJS come a un motore di modelli lato server qui (come jade, manubri, ecc ...). L'HTML visualizzato dal server contiene l'interfaccia utente come dovrebbe essere e non si attende il caricamento di alcuno script. La tua pagina può essere indicizzata da un motore di ricerca (se non viene eseguito alcun javascript).

Poiché l'interfaccia utente viene visualizzata sul server, nessuno dei gestori di eventi funzionerà e non c'è interattività (hai una pagina statica).

Tutti e due

Qui, il rendering iniziale è sul server. Quindi, l'HTML ricevuto dal browser ha l'interfaccia utente come dovrebbe essere. Una volta caricati gli script, il DOM virtuale viene nuovamente sottoposto a rendering per configurare i gestori di eventi dei componenti.

Qui, devi assicurarti di rieseguire il rendering dello stesso identico DOM virtuale (componente radice ReactJS) con lo stesso propsche hai usato per il rendering sul server. Altrimenti, ReactJS si lamenterà del fatto che i DOM virtuali lato server e lato client non corrispondono.

Poiché ReactJS differenzia i DOM virtuali tra i ri-rendering, il DOM reale non viene mutato. Solo i gestori di eventi sono associati agli elementi DOM reali.


1
Quindi, in caso di "entrambi", devo scrivere lo stesso codice due volte "uno per il rendering del server e uno per riprodurre questo DOM sul client? Giusto?
Simcha

10
È necessario eseguire lo stesso codice due volte. Una volta sul server e una volta sul client. Tuttavia, è necessario scrivere i componenti per tenerne conto, ad esempio non si dovrebbe eseguire alcun caricamento asincrono dei dati componentWillMount(), poiché eseguirà sia il client che il server. Avrai anche bisogno di una strategia per recuperare i dati in anticipo sul server e renderli disponibili per il rendering iniziale sul client, per assicurarti di ottenere lo stesso output.
Jonny Buchanan

3
È inoltre possibile verificare se il codice in esecuzione è sul lato server o lato client utilizzando typeof window == "undefined"e quindi recuperare i dati di conseguenza.
Gautham Badhrinathan

Hai un link a un esempio che si adatta alla tua implementazione?
Sawtaytoes

1
@IanW Tipicamente in questo caso l'HTML restituito dal server è molto "scarno", semplicemente importa il tuo JavaScript e gli stili e contiene un codice in <div>cui React scriverà.
Matt Holland,

48

Fonte immagine: blog di ingegneria di Walmart Labs

SSR

CSR

NB: SSR (Server Side Rendering), CSR (Client Side Rendering).

La differenza principale è che con SSR, la risposta del server al browser del client, include l'HTML della pagina da visualizzare. È anche importante notare che sebbene, con SSR, il rendering della pagina sia più veloce. La pagina non sarà pronta per l'interazione dell'utente finché i file JS non saranno stati scaricati e il browser non avrà eseguito React.

Uno svantaggio è che l'SSR TTFB (Time to First Byte) può essere leggermente più lungo. Comprensibilmente, perché il server impiega del tempo per creare il documento HTML, che a sua volta aumenta la dimensione della risposta del server.


4

In realtà mi stavo chiedendo la stessa ricerca un po 'e mentre la risposta che stai cercando è stata data nei commenti, ma sento che dovrebbe essere più prominente, quindi sto scrivendo questo post (che aggiornerò una volta che riesco a trovare un modo migliore in quanto trovo la soluzione architettonicamente almeno discutibile).

Avresti bisogno di scrivere i tuoi componenti con entrambi i modi in mente, quindi fondamentalmente mettendo gli ifinterruttori ovunque per determinare se sei sul client o sul server e quindi esegui come query DB (o qualsiasi altra cosa appropriata sul server) o una chiamata REST (sul cliente). Quindi dovresti scrivere endpoint che generano i tuoi dati ed esporli al client e il gioco è fatto.

Ancora una volta, felice di apprendere una soluzione più pulita.


2

Sono 2 modi separati per creare l'applicazione o possono essere usati insieme?

Possono essere usati insieme.

Se possiamo usarlo insieme, come farlo: dobbiamo duplicare gli stessi elementi sul lato server e sul lato client? Oppure, possiamo semplicemente costruire le parti statiche della nostra applicazione sul server e le parti dinamiche sul lato client, senza alcuna connessione al lato server che era già pre-renderizzato?

È meglio che venga eseguito il rendering dello stesso layout per evitare operazioni di ridisposizione e ridisegno, meno sfarfallio / lampeggiamento, la pagina sarà più fluida. Tuttavia, non è una limitazione. Potresti benissimo memorizzare nella cache l'SSR html (qualcosa che Electrode fa per ridurre i tempi di risposta) / inviare un html statico che viene sovrascritto dal CSR (rendering lato client).

Se stai appena iniziando con SSR, ti consiglierei di iniziare in modo semplice, SSR può diventare molto complesso molto rapidamente. Creare html sul server significa perdere l'accesso a oggetti come finestra, documento (li hai sul client), perdere la capacità di incorporare operazioni asincrone (pronte all'uso) e generalmente molte modifiche al codice per rendere il tuo codice compatibile SSR ( poiché dovrai usare webpack per impacchettare il tuo bundle.js). Cose come importazioni CSS, require vs import iniziano improvvisamente a morderti (questo non è il caso dell'app React predefinita senza webpack).

Lo schema generale dell'SSR è simile a questo. Un server Express che serve le richieste:

const app = Express();
const port = 8092;

// This is fired every time the server side receives a request
app.use(handleRender);
function handleRender(req, res) {
    const fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
    console.log('fullUrl: ', fullUrl);
    console.log('req.url: ', req.url);

    // Create a new Redux store instance
    const store = createStore(reducerFn);

    const urlToRender = req.url;
    // Render the component to a string
    const html = renderToString(
        <Provider store={store}>
            <StaticRouter location={urlToRender} context={{}}>
                {routes}
            </StaticRouter>
        </Provider>
    );
    const helmet = Helmet.renderStatic();

    // Grab the initial state from our Redux store
    const preloadedState = store.getState();

    // Send the rendered page back to the client
    res.send(renderFullPage(helmet, html, preloadedState));
}

Il mio suggerimento alle persone che iniziano con SSR sarebbe di fornire HTML statico. Puoi ottenere l'html statico eseguendo l'app CSR SPA:

document.getElementById('root').innerHTML

Non dimenticare, gli unici motivi per utilizzare SSR dovrebbero essere:

  1. SEO
  2. Caricamenti più veloci (lo sconto questo)

Hack: https://medium.com/@gagan_goku/react-and-server-side-rendering-ssr-444d8c48abfc

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.