Las URL del enrutador React no funcionan cuando se actualizan o se escriben manualmente
Estoy usando React-router y funciona bien mientras hago clic en los botones de enlace, pero cuando actualizo mi página web no carga lo que quiero.
Por ejemplo, yo estoy dentro localhost/joblist
y todo está bien porque llegué aquí presionando un enlace. Pero si actualizo la página web obtengo:
Cannot GET /joblist
Por defecto, no funcionó así. Inicialmente tenía mi URL como localhost/#/
y localhost/#/joblist
funcionaron perfectamente bien. Pero no me gusta este tipo de URL, así que al intentar borrarla #
, escribí:
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
Este problema no ocurre con localhost/
, este siempre devuelve lo que quiero.
Esta aplicación es de una sola página, por lo que /joblist
no necesita preguntar nada a ningún servidor.
Todo mi enrutador.
var routes = (
<Route name="app" path="/" handler={App}>
<Route name="joblist" path="/joblist" handler={JobList}/>
<DefaultRoute handler={Dashboard}/>
<NotFoundRoute handler={NotFound}/>
</Route>
);
Router.run(routes, Router.HistoryLocation, function (Handler) {
React.render(<Handler/>, document.body);
});
Lado del servidor versus lado del cliente
Lo primero que hay que entender acerca de esto es que ahora hay 2 lugares donde se interpreta la URL, mientras que solía haber solo 1 en "los viejos tiempos". En el pasado, cuando la vida era simple, algún usuario enviaba una solicitud al http://example.com/about
servidor, que inspeccionaba la parte de la ruta de la URL, determinaba que el usuario estaba solicitando la página Acerca de y luego devolvía esa página.
Con el enrutamiento del lado del cliente, que es lo que proporciona React Router, las cosas son menos simples. Al principio, el cliente aún no tiene ningún código JavaScript cargado. Entonces la primera solicitud siempre será al servidor. Luego, se devolverá una página que contiene las etiquetas de script necesarias para cargar React y React Router, etc. Solo cuando esos scripts se hayan cargado, comenzará la fase 2. En la fase 2, cuando el usuario hace clic en el enlace de navegación 'Acerca de nosotros', por ejemplo, la URL se cambia localmente solo a http://example.com/about
(lo que es posible gracias a History API ), pero no se realiza ninguna solicitud al servidor . En cambio, React Router hace lo suyo en el lado del cliente, determina qué vista de React renderizar y la renderiza. Suponiendo que su página Acerca de no necesita realizar ninguna llamada REST , ya está hecho. Ha pasado de Inicio a Acerca de nosotros sin que se haya activado ninguna solicitud del servidor.
Básicamente, cuando haces clic en un enlace, se ejecuta algo de JavaScript que manipula la URL en la barra de direcciones, sin provocar una actualización de la página , lo que a su vez hace que React Router realice una transición de página en el lado del cliente .
Pero ahora considere lo que sucede si copia y pega la URL en la barra de direcciones y se la envía por correo electrónico a un amigo. Tu amigo aún no ha cargado tu sitio web. Es decir, todavía está en la fase 1 . Todavía no se está ejecutando ningún React Router en su máquina. Entonces su navegador realizará una solicitud al servidor http://example.com/about
.
Y aquí es donde empiezan tus problemas. Hasta ahora, podías salirte con la tuya simplemente colocando un HTML estático en la raíz web de tu servidor. Pero eso daría errores 404 para todas las demás URL cuando se soliciten desde el servidor . Esas mismas URL funcionan bien en el lado del cliente , porque React Router está haciendo el enrutamiento por usted, pero fallan en el lado del servidor a menos que haga que su servidor las entienda.
Combinando enrutamiento del lado del servidor y del cliente
Si desea que la http://example.com/about
URL funcione tanto en el lado del servidor como en el del cliente, debe configurar rutas tanto en el lado del servidor como en el del cliente. Tiene sentido, ¿verdad?
Y aquí es donde comienzan tus elecciones. Las soluciones van desde evitar el problema por completo, a través de una ruta general que devuelve el código HTML de arranque, hasta el enfoque isomórfico completo en el que tanto el servidor como el cliente ejecutan el mismo código JavaScript.
Evitando el problema por completo: Hash History
Con Hash History , en lugar de Browser History , la URL de la página Acerca de se vería así:
http://example.com/#/about
La parte después del #
símbolo almohadilla ( ) no se envía al servidor. Entonces el servidor solo ve http://example.com/
y envía la página de índice como se esperaba. React Router recogerá la #/about
pieza y mostrará la página correcta.
Desventajas :
- URL 'feas'
- La renderización del lado del servidor no es posible con este enfoque. En lo que respecta a la optimización de motores de búsqueda (SEO), su sitio web consta de una única página sin apenas contenido.
Comodín
Con este enfoque, utiliza el Historial del navegador, pero simplemente configura un comodín en el servidor que envía /*
a index.html
, lo que efectivamente le brinda la misma situación que con el Historial de Hash. Sin embargo, tiene URL limpias y podría mejorar este esquema más adelante sin tener que invalidar todos los favoritos de sus usuarios.
Desventajas :
- Más complejo de configurar
- Todavía no hay buen SEO
Híbrido
En el enfoque híbrido, se amplía el escenario general agregando scripts específicos para rutas específicas. Podrías crear algunos scripts PHP simples para devolver las páginas más importantes de tu sitio con contenido incluido, para que Googlebot pueda al menos ver lo que hay en tu página.
Desventajas :
- Aún más complejo de configurar
- Sólo un buen SEO para aquellas rutas a las que le das un trato especial
- Duplicar código para representar contenido en el servidor y el cliente
isomórfico
¿Qué pasa si usamos Node.js como nuestro servidor para poder ejecutar el mismo código JavaScript en ambos extremos? Ahora, tenemos todas nuestras rutas definidas en una única configuración de enrutador de reacción y no necesitamos duplicar nuestro código de renderizado. Este es "el santo grial", por así decirlo. El servidor envía exactamente el mismo marcado con el que terminaríamos si la transición de página hubiera ocurrido en el cliente. Esta solución es óptima en términos de SEO.
Desventajas :
- El servidor debe (poder) ejecutar JavaScript. He experimentado con Java junto con Nashorn , pero no me funciona. En la práctica, esto significa principalmente que debes usar un servidor basado en Node.js.
- Muchos problemas ambientales complicados (uso
window
en el lado del servidor, etc.) - Curva de aprendizaje pronunciada
¿Cuál debo usar?
Elija aquel con el que pueda salirse con la suya. Personalmente, creo que el comodín es bastante sencillo de configurar, por lo que ese sería mi mínimo. Esta configuración le permite mejorar las cosas con el tiempo. Si ya está utilizando Node.js como plataforma de servidor, definitivamente investigaría cómo hacer una aplicación isomórfica. Sí, es difícil al principio, pero una vez que lo dominas, en realidad es una solución muy elegante al problema.
Básicamente, para mí, ese sería el factor decisivo. Si mi servidor se ejecuta en Node.js, me volvería isomórfico; de lo contrario, optaría por la solución general y simplemente la ampliaría (solución híbrida) a medida que pasa el tiempo y los requisitos de SEO lo exigen.
Si desea obtener más información sobre el renderizado isomórfico (también llamado "universal") con React, existen algunos buenos tutoriales sobre el tema:
- Reacciona al futuro con aplicaciones isomórficas
- El dolor y la alegría de crear aplicaciones isomórficas en ReactJS
- Cómo implementar JavaScript isomorfo de Node + React y por qué es importante
Además, para empezar, te recomiendo que consultes algunos kits de inicio. Elija uno que coincida con sus opciones para la pila de tecnología (recuerde, React es solo la V en MVC , necesita más cosas para crear una aplicación completa). Comience mirando el publicado por el propio Facebook:
- Crear aplicación de reacción
O elija uno de los muchos de la comunidad. Ahora hay un buen sitio que intenta indexarlos todos:
- Elija su proyecto inicial de React perfecto
Empecé con estos:
- Reaccionar kit de inicio isomórfico
- Ejemplo caliente universal de React Redux
Actualmente, estoy usando una versión casera de renderizado universal inspirada en los dos kits de inicio anteriores, pero ya están desactualizados.
¡Buena suerte con tu búsqueda!
Si está utilizando Apache como servidor web, puede insertar esto en su .htaccess
archivo:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
</IfModule>
Estoy usando react: "^16.12.0"
y react-router: "^5.1.2"
Este método es general y probablemente sea la forma más fácil de comenzar.