Si intenta describir en pocas palabras en qué consiste la función de enrutamiento en el front-end de las aplicaciones web, puede llegar a la conclusión de que cada marco popular tiene una idea completamente diferente de esto. Incluso comparando las versiones del mismo marco, podemos concluir que las funciones y las API de enrutamiento son más susceptibles a los cambios (a menudo sin compatibilidad con versiones anteriores). Por ejemplo, la cuarta versión del enrutamiento de React se ha rediseñado tan radicalmente que algunos proyectos populares en githab.com no han cambiado a esta versión.
Detrás de todo esto, hay una tendencia general, que, en mi opinión, es que la funcionalidad de enrutamiento en muchos marcos front-end populares está sobrecargada. En este sentido, se conecta estrechamente con otros componentes que podrían aislarse del enrutamiento (por ejemplo, navegación, historial, enlaces, etc.). Por lo tanto, probablemente, muchos están familiarizados con la sensación cuando el uso del enrutamiento se vuelve incómodo y su expansión es simplemente imposible. En comparación con los componentes flexibles y extensibles, el enrutamiento en marcos front-end populares parece mucho menos conveniente y no se puede expandir en absoluto. Esto es especialmente cierto en las primeras versiones (hasta la 4ta) de enrutamiento en React.
En esta publicación, analizaré algunos puntos históricos que condujeron a este estado de cosas con el enrutamiento, así como el uso de la biblioteca de enrutadores universales, junto con React.
¿Es necesario el enrutamiento?
Técnicamente, una aplicación web de una página puede funcionar sin enrutamiento. Por ejemplo, como no hay enrutamiento en la aplicación de escritorio. Todo funcionaría casi bien si la aplicación web de una página no fuera la misma aplicación de navegador web. Es decir, el usuario puede actualizar la página en cualquier momento presionando la tecla F5 o haciendo clic en el icono "Recargar" del navegador. Alternativamente, el usuario puede desplazar la historia hacia adelante o hacia atrás en cualquier momento haciendo clic en los iconos "Flecha izquierda" y "Flecha derecha", o presionando la tecla "Retroceso".
Por lo tanto, para una aplicación de una sola página, un cambio de componentes y un cambio en el estado interno de la aplicación siempre deben ir acompañados de un cambio en la URL.
¿Por qué es así el enrutamiento?
La función de enrutamiento en los marcos populares para aplicaciones web front-end, en mi opinión, se ve afectada por su conexión histórica con el enrutamiento en aplicaciones web clásicas (con renderizado de servidor).
Inicialmente, url era la dirección web de un documento web estático, y era muy simple. Luego, comenzó la adaptación de la arquitectura MVC a la web: Modelo 1 y Modelo 2. El último de ellos incluye un controlador frontal, que luego se dividió en dos partes: enrutamiento (que selecciona el controlador deseado) y el controlador mismo, que funciona con el modelo y Vista de renderizado. Como puede ver, en una aplicación web clásica, el enrutamiento determina la acción (controlador) e, indirectamente (a través del controlador), determina la vista que se debe representar en el servidor.
Es decir, la arquitectura de escritorio se adaptó una vez para trabajar con la aplicación web clásica en el servidor, y luego regresó al frente de la aplicación web en forma de enrutamiento, que se ponderó con las funciones que se necesitaban en el lado del servidor.
¿Qué ofrece la biblioteca de enrutadores universales?
La biblioteca de enrutadores universales ofrece descartar todo lo que es superfluo y dejar solo esa parte que se puede usar con o sin marco cuando se procesa tanto en el cliente como en el lado del servidor web (en aplicaciones web universales / isomorfas).
Después de rechazar todos los estratos del tiempo, el enrutador universal ofrece solo una función claramente definida. En función de la línea (hago hincapié en la línea nuevamente y no en el objeto del historial, la ubicación, etc.), llame a la función asincrónica, a la que se enviará la cadena de URL analizada como los parámetros reales. Eso es todo Cómo se vería en React:
import React from 'react'; import UniversalRouter from 'universal-router'; import App from './App'; import Link from './Link'; const routes = { path: '/', async action({next}) { const children = await next(); return ( <App> {children} </App> ); }, children: [ { path: '', async action() { return ( <div>Root route go to <Link href='/test'>Test</Link></div> ); }, }, { path: '/test', async action({next}) { const children = await next(); return ( <App> {children} </App> ); }, children: [ { path: '', async action() { return ( <div>Test route return to <Link href='/'>Root</Link></div> ); }, }, ] }, ], }; export const basename = ''; const router = new UniversalRouter(routes, { baseUrl: basename }); export default router;
Las rutas anidadas también son compatibles. Se definen en el campo secundario, y puede obtenerlos llamando a la función asincrónica next ().
¿Y cómo funciona esto con React?
Defina el método de navegación () para el historial, aunque en muchos casos es suficiente usar el método nativo push ()
import { createBrowserHistory } from 'history' import parse from 'url-parse' import deepEqual from 'deep-equal' const isNode = new Function('try {return this===global;}catch(e){return false;}')
También creamos el componente Enlace que activará la navegación:
import React from 'react'; import {basename} from './router'; import history from './history'; function noOp(){}; const createOnClickAnchor = (callback) => { return (e) => { e.preventDefault(); history.navigate(e.currentTarget.getAttribute('href')); callback(e); }; }; export default ({href, onClick = noOp, children, ...rest}) => ( <a href={basename + href} onClick={createOnClickAnchor(onClick)} {...rest} > {children} </a> );
Ahora está listo para renderizar el componente:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; import history from './history'; import router from './router'; const render = async (location) => { const element = await router.resolve(location); ReactDOM.render( element, document.getElementById('root'), ); }; render(history.location); history.listen(render);
Código del proyectoEnlaces utiles
1.
medium.com/@ippei.tanaka/universal-router-history-react-97ec79464573