Renderizando React.js en el server con Express.js y react-engine

React.js cada vez es más popular en el mundo del desarrollo web y una de las razones de esto es que permite crear código isomórfico, esto quiere decír que funciona tanto en el cliente (navegador) como en el servidor.

Este artículo usa una versión vieja de React, actualmente este separó las funciones de renderizado a un módulo propio llamado react-dom.

React.js en general es bastante fácil de usar en el servidor, simplemente hay que importar React.js y el componente que queramos renderizar y ejecutar el método de React.js llamado renderToString.

Ejemplo de como usar React.renderToString para renderizar nuestro componente como un string de código HTML

En este ejemplo la constante html es igual a un string con lo que renderice el componente Home.

Ahora si queremos usar esto en Express.js para renderizar en el servidor tendríamos que hacer algo así:

Ejemplo de como enviar el HTML por React.renderToString usando Express.js

De esta forma simplemente estamos enviando el html que generamos como un string usando Express.js.

Ahora esto tiene un problema y es que no estamos pudiendo hacer uso de una función que nos provee Express.js llamada res.render() la cual nos permite usas un sistema de templates para directamente renderizarlo desde Express.js en vez de usar res.send().

Para solucionar esto los ingenieros de PayPal desarrollaron un módulo llamado react-engine. Este módulo nos permite decirle a Express.js que use React.js como engine de templates y nos vuelve a habilitar el uso de res.render() para rendirizar nuestro HTML.

Introduciendo react-engine

Para hacer uso de react-engine necesitamos bajar este módulo usando el comando:

npm i -S react-engine

Una vez descargado lo importamos en nuestro server.js bajo el nombre de engine, luego de iniciar nuestra aplicación de Express.js de la forma tradicional registramos a react-engine como engine de archivos .jsx usando el método engine de nuestra aplicación de Express.js

Luego de esto le decimos a nuestra aplicación donde vamos a tener ubicados nuestras vistas, la extensión de los archivos de nuestras vistas y por último definimos que use react-engine para nuestras vistas.

Luego de esto ya podemos empezar a usar res.render() para renderizar nuestros componentes de React.js como vistas de nuestra aplicación como se ve en el ejemplo:

Ejemplo de como usar react-router para renderizar componentes de React.js usando res.render en Express.js

Esto se puede mejorar incorporando react-router para manejar el ruteo de nuestra aplicación tanto en el servidor como en el cliente, para esto hay que pasarle un objeto con la propiedad reactRoutes, cuyo valor sea la ubicación del archivo donde están las rutas, a la función engine.server.create al momento de definir como funciona el engine de archivos .jsx.

Dentro de nuestro server.js también vamos a definir nuestras rutas y al momento de llamar a res.render le vamos a pasar en vez del nombre de la ruta la propiedad url del objeto req (req.url) lo que va a hacer que react-router sepa cual vista renderizar y como segundo parámetro le pasamos cualquier datos que queramos pasar a nuestra vista (las props que reciba).

Luego necesitamos crear ese archivo de routes que van a estar definidas con react-router y exportarlo. Por último podemos crear un archivo que vamos a usar en el cliente (navegador) para iniciar nuestra aplicación usando react-engine para usar las rutas de react-router.

Ejemplo de como usar react-engine con react-router tanto cn el servidor como en el cliente, en el ejemplo se basa en que tenés un componente Home como el del ejemplo anterior sin react-router

El último paso sería usar Browserify + Babelify para generar un bundle para el código del cliente y con esto ya tendríamos nuestra aplicación usando React.js para manejar nuestras vistas tanto en el servidor como en el cliente.