Ahora tenemos una aplicación completamente funcional, pero ¿por qué detenernos aquí? Convirtamos esta aplicación en una isomórfica.
Isomórfico (o universal) es un término que significa que el mismo código JavaScript puede ejecutarse en el cliente y en el servidor sin modificaciones, de modo que el servidor puede generar la página y servirla como HTML plano.
En esencia, la renderización de servidores es un concepto simple logrado con una sola llamada de función en Node.js:
1const appHTML =renderToString(<App/>);
javascript
Sin embargo, Node.js no sabe nada sobre JSX (la sintaxis usada por React; ), así que lo que podemos hacer es usar Webpack para construir un paquete de servidor, igual que el paquete de cliente.
Crea el archivo webpack.server.config.js con el siguiente contenido:
12345678910111213141516171819202122232425262728293031323334var fs =require("fs");var ruta =require("ruta");module.exports={ entry: ruta.resolve(__dirname, "server.js"), output:{ nombre de archivo: "server.bundle.js"}, target: "node", externals: fs .readdirSync(ruta. resolve(__dirname, "node_modules")).concat(["react-dom/server", "react/addons"]).reduce(function(ext, mod){ ext[mod]="commonjs "+ mod;return ext;},{}), node:{ __filename:true, __dirname:true}, module:{ loaders:[{ loader: "babel", exclude:/node_modules/}]}};
javascript
Este archivo le dice a Webpack que tome el server.js como punto de entrada para generar el archivo server.bundle.js con todas sus dependencias agrupadas.
El objetivo: la opción «nodo» le dice a webpack que no toque ningún módulo incorporado en Node.js. Sin embargo, Webpack cargará los módulos del directorio node_modules y los agrupará también. Para evitar esto, usamos la opción de externos. Un módulo listado como externo no será empaquetado. Para más información sobre los externos, ver esta página.
Desafortunadamente, el uso de elementos externos supone un entorno de navegación, por lo que algo como require($0027twilio$0027) se convertirá en la variable global twilio. Para mantener nuestras declaraciones require, necesitamos crear un objeto con una clave/valor de cada nombre de módulo y prefijar el valor con commonjs.
A continuación, las opciones se pasan al nodo para que __nombre del archivo y __nombre del directorio funcionen como se espera.
Abrir server.js e importar los módulos de Reactancia que usaremos (gracias a Webpack y Babel, ahora podemos usar importar en lugar de requerir):
123importReactfrom "react";import{ renderToString }from "react-dom/server";importAppfrom"./src/components/index";
javascript
Y reemplace la definición de la ruta con lo siguiente:
1234567app.get("/",function(req, res){const appHtml =renderToString(<App/>); res.render("index",{ appHtml: appHtml });});
javascript
Fíjate que estamos usando src/componentes/index.js en lugar de src/app.js para renderizar la aplicación en el lado del servidor. La razón es que src/app.js hace referencia al DOM (Document Object Model), que es un concepto de navegador que no existe en el servidor.
Asimismo, como el componenteDidMount puede contener referencias al DOM, no se ejecutará en el lado del servidor. Pero no te preocupes, cuando la aplicación React se cargue en el cliente (recuerda que el punto de entrada en el cliente sigue siendo src/app.js), esta función se ejecutará.
Además, modifica /views/index.ejs para que pueda renderizar el HTML generado:
html
En el EJS, la etiqueta <%- da como resultado el valor no escapado del objeto en la plantilla (en contraste con la más comúnmente usada <%=).
Asegúrate de no dejar ningún espacio entre la etiqueta del divisor de apertura y cierre, de lo contrario, React se quejará del espacio en blanco.
Finalmente, tenemos que modificar el script de inicio de package.json para generar el paquete del servidor cada vez que se inicia el servidor. Vamos a organizar nuestros scripts de esta manera:
12345678... "scripts":{"start": "npm run build && node server.bundle.js", "build:client": "webpack", "build:server": "webpack --config webpack.server.config.js", "build": "npm run build:client && npm run build:server"},...
javascript
npm run build activará la generación de los paquetes de servidor y cliente y el nodo server.bundle.js iniciará el servidor con el paquete generado en lugar de server.js.
Escriba npm start y pruebe la aplicación. Debería funcionar como antes, pero con las ventajas del javascript isomórfico.