Representación del lado del servidor de ReactJS frente a la representación del lado del cliente


120

Acabo de comenzar a estudiar ReactJS y descubrí que te brinda 2 formas de renderizar páginas: del lado del servidor y del lado del cliente. Pero no puedo entender cómo usarlo juntos. ¿Son dos formas distintas de crear la aplicación o se pueden utilizar juntas?

Si podemos usarlo juntos, ¿cómo hacerlo? ¿Necesitamos duplicar los mismos elementos en el lado del servidor y en el lado del cliente? O, ¿podemos simplemente construir las partes estáticas de nuestra aplicación en el servidor y las partes dinámicas en el lado del cliente, sin ninguna conexión con el lado del servidor que ya fue renderizado previamente?


1
Respuesta corta, NO: puede desacoplar, enviar html estático y cambiarlo por completo en el renderizado del cliente. He agregado detalles en mi respuesta.
Kira

Respuestas:


108

Para un sitio web / aplicación web determinada, puede usar react en el lado del cliente , en el servidor o en ambos .

Lado del cliente

Aquí, está ejecutando ReactJS completamente en el navegador. Esta es la configuración más simple e incluye la mayoría de los ejemplos (incluidos los de http://reactjs.org ). El HTML inicial representado por el servidor es un marcador de posición y toda la interfaz de usuario se representa en el navegador una vez que se cargan todos los scripts.

Lado del servidor

Piense en ReactJS como un motor de plantillas del lado del servidor aquí (como jade, manubrios, etc.). El HTML generado por el servidor contiene la interfaz de usuario como debería ser y no esperas a que se cargue ningún script. Su página puede ser indexada por un motor de búsqueda (si uno no ejecuta ningún javascript).

Dado que la interfaz de usuario se representa en el servidor, ninguno de sus controladores de eventos funcionaría y no hay interactividad (tiene una página estática).

Ambos

Aquí, el renderizado inicial está en el servidor. Por lo tanto, el HTML recibido por el navegador tiene la interfaz de usuario como debería ser. Una vez que se cargan los scripts, el DOM virtual se vuelve a renderizar una vez más para configurar los controladores de eventos de sus componentes.

Aquí, debe asegurarse de volver a renderizar exactamente el mismo DOM virtual (componente raíz de ReactJS) con el mismo propsque utilizó para renderizar en el servidor. De lo contrario, ReactJS se quejará de que los DOM virtuales del lado del servidor y del lado del cliente no coinciden.

Dado que ReactJS diferencia los DOM virtuales entre re-renderizaciones, el DOM real no está mutado. Solo los controladores de eventos están vinculados a los elementos DOM reales.


1
Entonces, en el caso de "ambos", necesito escribir el mismo código dos veces "uno para la representación del servidor y otro para reproducir este DOM en el cliente, ¿verdad?
Simcha

10
Necesita ejecutar el mismo código dos veces. Una vez en el servidor y una vez en el cliente. Sin embargo, debe escribir sus componentes para tener esto en cuenta, por ejemplo, no debe realizar ninguna recuperación de datos asíncronos componentWillMount(), ya que ejecutará tanto el cliente como el servidor. También necesitará una estrategia para obtener datos por adelantado en el servidor y hacerlos disponibles para el procesamiento inicial en el cliente, para asegurarse de obtener el mismo resultado.
Jonny Buchanan

3
También puede verificar si el código que se está ejecutando está en el lado del servidor o en el lado del cliente typeof window == "undefined"y luego buscar sus datos en consecuencia.
Gautham Badhrinathan

¿Tiene un enlace a un ejemplo que se ajuste a su implementación?
Sawtaytoes

1
@IanW Normalmente, en este caso, el HTML devuelto por el servidor es muy "básico", simplemente importa su JavaScript y estilos y contiene un código en el <div>que React escribirá.
Matt Holland

48

Fuente de la imagen: Blog de ingeniería de Walmart Labs

SSR

RSE

NB: SSR (representación del lado del servidor), CSR (representación del lado del cliente).

La principal diferencia es que con SSR, la respuesta del servidor al navegador del cliente, incluye el HTML de la página que se va a representar. También es importante tener en cuenta que, aunque con SSR, la página se procesa más rápido. La página no estará lista para la interacción del usuario hasta que los archivos JS se hayan descargado y el navegador haya ejecutado React.

Una desventaja es que el SSR TTFB (tiempo hasta el primer byte) puede ser un poco más largo. Es comprensible, porque el servidor tarda algo de tiempo en crear el documento HTML, lo que a su vez aumenta el tamaño de respuesta del servidor.


4

En realidad, me preguntaba lo mismo investigando un poco y, aunque la respuesta que está buscando se dio en los comentarios, creo que debería ser más prominente, por lo tanto, estoy escribiendo esta publicación (que actualizaré una vez que pueda encontrar un mejor manera ya que encuentro la solución arquitectónicamente al menos cuestionable).

Debería escribir sus componentes con ambas formas en mente, por lo que básicamente debe colocar ifinterruptores en todas partes para determinar si está en el cliente o en el servidor y luego hacerlo como una consulta DB (o lo que sea apropiado en el servidor) o una llamada REST (en el cliente). Luego, tendría que escribir puntos finales que generen sus datos y exponerlos al cliente y listo.

Nuevamente, feliz de conocer una solución más limpia.


2

¿Son dos formas distintas de crear la aplicación o se pueden utilizar juntas?

Se pueden usar juntos.

Si podemos usarlo juntos, ¿cómo hacerlo? ¿Necesitamos duplicar los mismos elementos en el lado del servidor y en el lado del cliente? O, ¿podemos simplemente construir las partes estáticas de nuestra aplicación en el servidor y las partes dinámicas en el lado del cliente, sin ninguna conexión con el lado del servidor que ya fue renderizado previamente?

Es mejor renderizar el mismo diseño para evitar operaciones de reflujo y repintado, menos parpadeos / parpadeos, su página será más fluida. Sin embargo, no es una limitación. Puede almacenar en caché el html SSR (algo que hace Electrode para reducir el tiempo de respuesta) / enviar un html estático que es sobrescrito por el CSR (render del lado del cliente).

Si recién está comenzando con SSR, le recomendaría comenzar simple, SSR puede volverse muy complejo muy rápidamente. Crear html en el servidor significa perder el acceso a objetos como ventana, documento (los tiene en el cliente), perder la capacidad de incorporar operaciones asíncronas (listas para usar) y, en general, muchas ediciones de código para que su código sea compatible con SSR ( ya que tendrá que usar webpack para empaquetar su bundle.js). Cosas como las importaciones de CSS, requieren vs importación de repente comienzan a morderlo (este no es el caso en la aplicación React predeterminada sin paquete web).

El patrón general de SSR se ve así. Un servidor Express que atiende solicitudes:

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));
}

Mi sugerencia para las personas que comienzan con SSR sería ofrecer html estático. Puede obtener el HTML estático ejecutando la aplicación CSR SPA:

document.getElementById('root').innerHTML

No olvide que las únicas razones para usar SSR deben ser:

  1. SEO
  2. Cargas más rápidas (lo descartaría)

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.