Reaccione al futuro con aplicaciones isomórficas
Recientemente, con la creación de marcos web modernos como AngularJS y Ember, hemos visto un impulso para renderizar en el cliente y usar solo un servidor para una API. Ahora estamos viendo un posible regreso o, más bien, una combinación de ambas arquitecturas. La arquitectura web definitivamente pasa por ciclos. Comenzamos renderizando todo en el servidor y enviándolo al cliente. Luego apareció JavaScript y comenzamos a usarlo para interacciones simples con páginas. En algún momento, JavaScript creció y nos dimos cuenta de que podía usarse para crear aplicaciones grandes que representaran todo en el cliente y que usaran el servidor para recuperar datos a través de una API.
Las cosas a menudo cierran el círculo en la ingeniería de software. La web en particular comenzó con servidores que entregaban contenido al cliente. Recientemente, con la creación de marcos web modernos como AngularJS y Ember, hemos visto un impulso para renderizar en el cliente y usar solo un servidor para una API . Ahora estamos viendo un posible regreso o, más bien, una combinación de ambas arquitecturas.
¿Qué es reaccionar?
React es una biblioteca de JavaScript para crear interfaces de usuario.
Según el sitio web oficial . Es una forma de crear componentes front-end reutilizables. Simple y llanamente, ese es el objetivo de React.
¿Qué lo hace diferente?
React ha alcanzado rápidamente una inmensa popularidad en la comunidad de JavaScript. Hay varias razones para su éxito. Una es que Facebook lo creó y lo usa. Esto significa que muchos desarrolladores de Facebook trabajan con él, corrigiendo errores, sugiriendo funciones, etc.
Otra razón de su rápida popularidad es que es diferente. Es diferente a AngularJS , Backbone.js , Ember , Knockout y prácticamente a cualquiera de los otros frameworks JavaScript MV* populares que han surgido durante la revolución de JavaScript en los últimos años. La mayoría de estos otros marcos operan con la idea de vincularse bidireccionalmente al DOM y actualizarlo en función de los eventos. También todos requieren que el DOM esté presente ; Entonces, cuando trabajas con uno de estos marcos y quieres que cualquiera de tus marcas se represente en el servidor, debes usar algo como PhantomJS.
DOM virtual
React se describe a menudo como la "V" en una aplicación MVC. Pero hace V de manera bastante diferente a otros marcos MV*. Es diferente de cosas como manillares, plantillas de subrayado y plantillas de AngularJS. React opera según el concepto de un "DOM virtual". Mantiene este DOM virtual en la memoria, y cada vez que se realiza un cambio en el DOM, React hace una rápida comparación de los cambios, los agrupa todos en una sola actualización y accede al DOM real de una vez.
Esto tiene enormes ramificaciones. En primer lugar, en cuanto al rendimiento, no se realizan actualizaciones DOM constantemente, como ocurre con muchos de los otros marcos de JavaScript. El DOM es un gran cuello de botella en el rendimiento del front-end. La segunda ramificación es que React puede renderizar en el servidor con la misma facilidad que en el cliente.
React expone un método llamado React.renderToString()
. Este método le permite pasar un componente, que a su vez lo representa junto con cualquier componente secundario que utilice, y simplemente devuelve una cadena. Luego puede tomar esa cadena de HTML y simplemente enviarla al cliente.
Ejemplo
Estos componentes están construidos con una sintaxis llamada JSX. Al principio, JSX parece un extraño híbrido HTML-JavaScript:
var HelloWorld = React.createClass({ displayName: "HelloWorld", render() { return ( h1Hello {this.props.message}/h1 ); }});React.render(HelloWorld message="world" /, document.body);
Lo que debe hacer con este .jsx
formato es pasarlo (o "transpilar") webpack
, grunt
, gulp
o su "renderizador" de su elección y luego escupir JavaScript que se ve así:
var HelloWorld = React.createClass({ displayName: "HelloWorld", render: function() { return ( React.createElement("h1", null, "Hello ", this.props.message) ); }});React.render(React.createElement(HelloWorld, {message: "world"}), document.body);
Eso es a lo que se transforma nuestro HelloWorld.jsx
componente: nada más que un simple JavaScript. Algunos considerarían que esto es una violación de la separación de preocupaciones al mezclar JavaScript con HTML. Al principio, esto parece exactamente lo que estamos haciendo. Sin embargo, después de trabajar con React por un tiempo, te das cuenta de que la proximidad del marcado de tu componente al JavaScript te permite desarrollarlo más rápidamente y mantenerlo por más tiempo porque no estás saltando de un lado a otro entre archivos HTML y JavaScript. Todo el código de un componente determinado se encuentra en un solo lugar.
React.render
adjunta su HelloWorld
componente al body
. Naturalmente, ese podría ser cualquier elemento allí. Esto hace que se active el método del componente render
y el resultado se agrega al DOM dentro de la body
etiqueta.
Con un componente React, todo lo que pase como atributos (por ejemplo, HelloWorld message="world" /
) tendrá acceso en el archivo this.props
. Entonces, en el HelloWorld
componente, this.props.message
es world
. Además, mire un poco más de cerca la parte JSX del código:
return ( h1Hello {this.props.message}/h1);
Primero notarás que debes envolver el HTML entre paréntesis. En segundo lugar, this.props.message
está envuelto en tirantes. Las llaves le dan acceso al componente a través de this
.
Cada componente también tiene acceso a su "estado". Con React, cada componente administra su estado con algunos métodos API simples getState
y setState
también getInitialState
cuando el componente se carga por primera vez. Siempre que cambia el estado, el render
método simplemente vuelve a representar el componente. Por ejemplo:
var Search = React.createClass({ getInitialState() { return { search: "" }; }, render() { return ( div className="search-component" input type="text" onChange={this.changeSearch} / spanYou are searching for: {this.state.search}/span /div ); }, changeSearch(event) { var text = event.target.value; this.setState({ search: text }); }});React.render(Search /, document.body);
En este ejemplo, la getInitialState
función simplemente devuelve un objeto literal que contiene el estado inicial del componente.
La render
función devuelve JSX para nuestros elementos; entonces, an input
y a span
, ambos envueltos en a div
. Tenga en cuenta que solo se puede devolver un elemento en JSX como padre. En otras palabras, no puedes regresar div/divdiv/div
; solo puedes devolver un elemento con varios hijos.
Observe la onChange={this.changeSearch}
. Esto le dice al componente que active la changeSearch
función cuando el evento de cambio se active en la entrada.
La changeSearch
función recibe el event
evento disparado del DOM y puede tomar el texto actual de la entrada. Luego, llamamos setState
y pasamos el texto. Esto hace render
que se dispare nuevamente y {this.state.search}
reflejará el nuevo cambio.
Hay muchas otras API en React disponibles para trabajar, pero en un nivel alto, lo que hicimos anteriormente es lo más fácil posible para crear un componente de React simple.
JavaScript isomórfico
Con React, podemos crear aplicaciones "isomorfas".
"i·so·mór·fico: “correspondiente o similar en forma y relaciones”"
Esto ya se convirtió en una palabra de moda en 2015. Básicamente, solo significa que podemos usar el mismo código en el cliente y en el servidor.
Este enfoque tiene muchos beneficios.
Eliminar la FOUC
Con AngularJS, Ember (por ahora) y arquitectura tipo SPA, cuando un usuario accede a la página por primera vez, todos los activos deben descargarse. Con las aplicaciones SPA, esto puede tardar un segundo y la mayoría de los usuarios hoy en día esperan un tiempo de carga de menos de dos segundos. Mientras se carga el contenido, la página no se muestra. A esto se le llama “flash de contenido sin estilo” (FOUC). Un beneficio de un enfoque isomórfico para crear aplicaciones es que obtiene los beneficios de velocidad de renderizar en el servidor y aún puede renderizar componentes después de que la página se carga en el cliente.
El trabajo de una aplicación isomórfica no es reemplazar la API del servidor tradicional, sino simplemente ayudar a eliminar FOUC y brindar a los usuarios la experiencia mejor y más rápida a la que se están acostumbrando.
Código compartido
Un gran beneficio es poder utilizar el mismo código en el cliente y en el servidor. Simplemente cree sus componentes y funcionarán en ambos lugares. En la mayoría de los sistemas, como Rails , ASP.NET MVC , normalmente tendrá erb
vistas cshtml
para renderizar en el servidor. Luego debes tener plantillas del lado del cliente, como Manillars o Hogan.js, que a menudo duplican la lógica. Con React, los mismos componentes funcionan en ambos lugares.
Mejora progresiva
La representación del servidor le permite enviar el HTML básico que un cliente necesita para mostrar un sitio web. Luego puede mejorar la experiencia o renderizar más componentes en el cliente.
Ofrecer una experiencia agradable a un usuario de un teléfono plegable en África, así como una experiencia mejorada a un usuario de una MacBook Pro de 15 pulgadas con pantalla Retina, conectada al nuevo monitor 4K, suele ser una tarea bastante tediosa.
React va más allá de simplemente compartir componentes. Cuando renderiza componentes de React en el servidor y envía el HTML al cliente, React en el lado del cliente nota que el HTML ya existe. Simplemente adjunta controladores de eventos a los elementos existentes y ya está listo para comenzar.
Esto significa que puede enviar sólo el HTML necesario para representar la página; luego, cualquier elemento adicional se puede incorporar y representar en el cliente según sea necesario. Obtiene el beneficio de una carga rápida de la página mediante la representación del servidor y puede reutilizar los componentes.
Creación de una aplicación Express isomórfica
Express es uno de los servidores web Node.js más populares. Ponerse en marcha con el renderizado React con Express es muy fácil.
Agregar renderizado de React a una aplicación Express requiere solo unos pocos pasos. Primero, agregue node-jsx
y react
a su proyecto con esto:
npm install node-jsx --savenpm install react --save
Creemos un app.jsx
archivo básico en el public/javascripts/components
directorio, que requiere nuestro Search
componente anterior:
var React = require("react"), Search = require("./search");var App = React.createClass({ render() { return ( Search / ); }});module.exports = App;
Aquí, estamos requiriendo react
y nuestro Search.jsx
componente. En el App
método de renderizado, simplemente podemos usar el componente con Search /
.
Luego, agregue lo siguiente a uno de sus enrutadores donde planea renderizar con React:
require("node-jsx").install({ harmony: true, extension: ".jsx"});
Todo lo que esto hace es permitirnos utilizar require
para capturar .jsx
archivos. De lo contrario, Node.js no sabría cómo analizarlos. La harmony
opción permite componentes estilo ECMAScript 6.
A continuación, solicite su componente y páselo a React.createFactory
, que devolverá una función que puede llamar para invocar el componente:
var React = require("react"), App = React.createFactory(require("../public/javascripts/components/app")), express = require("express"), router = express.Router();
Luego, en una ruta, simplemente llama React.renderToString
y pásale tu componente:
router.get("/", function(req, res) { var markup = React.renderToString( App() ); res.render("index", { markup: markup });});
Finalmente, en su opinión, simplemente genere el marcado:
body div {{{markup}}} /div/body
Eso es todo por el código del servidor. Veamos lo que es necesario del lado del cliente.
paquete web
Webpack es un paquete de JavaScript. Agrupa todos sus activos estáticos, incluidos JavaScript, imágenes, CSS y más, en un solo archivo. También le permite procesar los archivos a través de diferentes tipos de cargadores. Puede escribir su JavaScript con la sintaxis de módulos CommonJS o AMD.
Para .jsx
los archivos React, solo necesitará configurar webpack.config
un poco su archivo para poder compilar todos sus jsx
componentes.
Comenzar con Webpack es fácil:
npm install webpack -g # Install webpack globallynpm install jsx-loader --save # Install the jsx loader for webpack
A continuación, cree un webpack.config.js
archivo.
var path = require("path");module.exports = [{ context: path.join(__dirname, "public", "javascripts"), entry: "app", output: { path: path.join(__dirname, "public", "javascripts"), filename: "bundle.js" }, module: { loaders: [ { test: /.jsx$/, loader: "jsx-loader?harmony"} ] }, resolve: { // You can now require('file') instead of require('file.coffee') extensions: ["", ".js", ".jsx"], root: [path.join(__dirname, "public", "javascripts")], modulesDirectories: ["node_modules"] }}];
Analicemos esto:
context
Esta es la raíz de sus archivos JavaScript.entry
Este es el archivo principal que cargará los demás archivos utilizandorequire
la sintaxis de CommonJS de forma predeterminada.output
Esto le indica a Webpack que genere el código en un paquete, con una ruta depublic/javascripts/bundle.js
.
El module
objeto es donde configuras los "cargadores". Un cargador simplemente le permite probar una extensión de archivo y luego pasar ese archivo a través de un cargador. Existen muchos cargadores para cosas como CSS, Sass, HTML, CoffeeScript y JSX. Aquí solo tenemos uno jsx-loader?harmony
. Puede agregar opciones como una "cadena de consulta" al nombre del cargador. Aquí, ?harmony
nos permite utilizar la sintaxis ECMAScript 6 en nuestros módulos. Le test
dice a Webpack que pase cualquier archivo al .jsx
final a jsx-loader
.
En resolve
vemos algunas otras opciones. Primero, extensions
le dice a Webpack que omita las extensiones de ciertos tipos de archivos cuando archivamos require
. Esto nos permite simplemente hacer require(“./file”)
, en lugar de require(“./file.js”)
. También vamos a configurar un root
, que es simplemente la raíz desde donde se solicitarán nuestros archivos. Finalmente, permitiremos que Webpack extraiga módulos del node_modules
directorio con la modulesDirectories
opción. Esto nos permite instalar algo como Manillar con npm install handlebars
y simplemente require(“handlebars”)
, como lo haría en una aplicación Node.js.
Código del lado del cliente
En public/javascripts/app.js
, requeriremos el mismo App
componente que requerimos en Express:
var React = require("react"), App = React.createFactory(require("components/app"));if (typeof window !== "undefined") { window.onload = function() { React.render(App(), document.getElementById("content")); };}
Vamos a comprobar que estamos en el navegador con el archivo typeof window !== “undefined”
. Luego, lo adjuntaremos al onload
evento de la ventana, llamaremos React.render
y pasaremos nuestro archivo App()
. El segundo argumento que necesitamos aquí es un elemento DOM para montar. Este debe ser el mismo elemento en el que representamos el marcado de React en el servidor; en este caso, el #content
elemento.
El Search
componente del ejemplo anterior se representó en el servidor y se envió al cliente. ¡React del lado del cliente ve el marcado renderizado y adjunta solo los controladores de eventos! Esto significa que veremos una página inicial mientras se carga JavaScript.
Todo el código anterior está disponible en GitHub .
Conclusión
La arquitectura web definitivamente pasa por ciclos. Comenzamos renderizando todo en el servidor y enviándolo al cliente. Luego apareció JavaScript y comenzamos a usarlo para interacciones simples con páginas. En algún momento, JavaScript creció y nos dimos cuenta de que podía usarse para crear aplicaciones grandes que representaran todo en el cliente y que usaran el servidor para recuperar datos a través de una API.
En 2015, estamos empezando a darnos cuenta de que tenemos estos servidores potentes, con toneladas de memoria y CPU, y que hacen un muy buen trabajo al renderizar cosas para nosotros. Este enfoque isomórfico para crear aplicaciones podría brindarnos lo mejor de ambos mundos : usar JavaScript en ambos lugares y brindar al usuario una buena experiencia al enviar algo que pueda ver rápidamente y luego desarrollarlo con JavaScript del lado del cliente.
React es uno de los primeros de los que seguramente serán muchos marcos que permiten este tipo de comportamiento. Los desarrolladores de Ember también están trabajando en aplicaciones de estilo isomórfico. ¡Ver cómo funciona todo esto definitivamente será divertido!
Recursos
- Reaccionar
- Lecciones de reacción, Egghead.io
- Expresar
- "Ejemplos isomórficos", React.rocks
- Paquete web , GitHub
- Cargador JSX para Webpack , Pete Hunt, GitHub
Otras lecturas
- Cómo escalar las aplicaciones de React
- La belleza de reaccionar nativo
- Representación del lado del servidor con React, Node y Express
- Componentes con estilo: aplicación de las mejores prácticas en sistemas basados en componentes
(rb, al, il, mrn)Explora más en
- Codificación
- javascript
- Aplicaciones
- Nodo.js
- API
- Reaccionar
Deja un comentario