react example javascript url reactjs router react-router

javascript - example - react-router-dom



Las URL del enrutador de reacción no funcionan al actualizar o escribir manualmente (30)

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, estoy en 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 y funcionaron perfectamente bien. Pero no me gusta este tipo de URL, así que tratando de borrar ese # , 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.

EDITAR: Esta aplicación es de una sola página, por lo que /joblist no necesita preguntar nada a ningún servidor.

EDIT2: 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); });


Agregar más información a la respuesta de Joshua Dyck .

Si está utilizando Firebase y desea utilizar tanto la ruta raíz como una ruta de subdirectorio, debe agregar el siguiente código en su firebase.json :

{ "hosting": { "rewrites": [ { "source": "*", "destination": "/index.html" }, { "source": "/subdirectory/**", "destination": "/subdirectory/index.html" } ] } }

Ejemplo:

Estás construyendo un sitio web para un cliente. Desea que el propietario del sitio web agregue información en https://your.domain.com/management mientras que los usuarios del sitio web navegarán a https://your.domain.com .

En este caso, su firebase.json archivo se verá así:

{ "hosting": { "rewrites": [ { "source": "*", "destination": "/index.html" }, { "source": "/management/**", "destination": "/management/index.html" } ] } }


Arreglar el error "no se puede OBTENER / URL" al actualizar o al llamar a la URL directamente.

Configure su webpack.config.js para esperar el enlace dado en rutas como esta.

package.json "dependencies": { "babel-polyfill": "^6.23.0", "ejs": "^2.5.6", "express": "^4.15.2", "prop-types": "^15.5.6", "react": "^15.5.4", "react-dom": "^15.5.4", "react-redux": "^5.0.4", "react-router": "^3.0.2", "react-router-redux": "^4.0.8", "redux": "^3.6.0", "redux-persist": "^4.6.0", "redux-thunk": "^2.2.0", "webpack": "^2.4.1" }


Como estoy usando .Net Core MVC, algo como esto me ayudó:

` expressApp.get(''/*'', (request, response) => { response.sendFile(path.join(__dirname, ''../public/index.html'')); });`

Básicamente en el lado de MVC, todas las rutas que no coinciden se ajustarán a las Home/Index especificadas startup.cs . En el interior Index , es posible obtener la url de solicitud original y pasarla donde sea necesario.

startup.cs

public class HomeController : Controller { public IActionResult Index() { var url = Request.Path + Request.QueryString; return App(url); } [Route("App")] public IActionResult App(string url) { return View("/wwwroot/app/build/index.html"); } }


Me gusta esta forma de manejarlo. Intente agregar: yourSPAPageRoute / * en el lado del servidor para deshacerse de este problema.

Seguí este enfoque porque incluso la API nativa de Historial HTML5 no admite la redirección correcta en la actualización de la página (que yo sepa).

Nota: La respuesta seleccionada ya ha abordado esto, pero estoy tratando de ser más específico.

Ruta Express

Probado y solo quería compartir esto.

Espero eso ayude.


Para aquellos que usan IIS 10, esto es lo que debe hacer para hacer esto bien. Asegúrese de estar usando browserHistory con esto. En cuanto a la referencia, daré el código para el enrutamiento, pero esto no es lo que importa, lo que importa es el siguiente paso después del código del componente a continuación:

module.exports = { entry: ''./app/index.js'', output: { path: path.join(__dirname, ''/bundle''), filename: ''index_bundle.js'', publicPath: ''/'' },

Dado que el problema es que IIS recibe una solicitud de los navegadores del cliente, interpretará la URL como si estuviera pidiendo una página, luego devolverá una página 404 ya que no hay una página disponible. Haz lo siguiente:

  1. Abrir IIS
  2. Expanda el servidor y luego abra la carpeta Sitios
  3. Haga clic en el sitio web / aplicación
  4. Ir a las páginas de error
  5. Abra el elemento de estado de error 404 en la lista
  6. En lugar de la opción "Insertar contenido del archivo estático en la respuesta de error", cámbielo a "Ejecutar una URL en este sitio" y agregue el valor de barra "/" a la URL.

Y ahora funcionará bien.

Espero que ayude. :-)


Si está alojando en IIS; Agregar esto a mi configuración web resolvió mi problema

app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); routes.MapSpaFallbackRoute( name: "spa-fallback", defaults: new { controller = "Home", action = "Index" }); });

Puede hacer una configuración similar para cualquier otro servidor


Si está utilizando Express o algún otro marco en el back-end, puede agregar la configuración similar a la siguiente y verificar la ruta pública de Webpack en la configuración, debería funcionar bien incluso en la recarga si está utilizando BrowserRouter

<httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL"> <remove statusCode="500" subStatusCode="100" /> <remove statusCode="500" subStatusCode="-1" /> <remove statusCode="404" subStatusCode="-1" /> <error statusCode="404" path="/" responseMode="ExecuteURL" /> <error statusCode="500" prefixLanguageFilePath="" path="/error_500.asp" responseMode="ExecuteURL" /> <error statusCode="500" subStatusCode="100" path="/error_500.asp" responseMode="ExecuteURL" /> </httpErrors>


Si está utilizando Firebase, todo lo que tiene que hacer es asegurarse de tener una propiedad de reescritura en su archivo firebase.json en la raíz de su aplicación (en la sección de alojamiento).

Por ejemplo:

<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>

Espero que esto le ahorre a alguien más un montón de frustración y pérdida de tiempo.

Feliz codificación ...

Lecturas adicionales sobre el tema:

https://firebase.google.com/docs/hosting/full-config#rewrites

Firebase CLI: "Configurar como una aplicación de una sola página (reescribir todas las URL en /index.html)"


Suponga que tiene la siguiente definición de ruta de inicio

<Route exact path="/" render={routeProps => ( <Home routeProps={routeProps}/> )}/> {/*optional catch-all router */} <Route render={routeProps => ( <div><h4>404 not found</h4></div> )}/>

En su componente Home, puede interceptar la solicitud en el evento ComponentWillMount,

const searchPath = this.props.routeProps.location.search; if (searchPath){ this.props.routeProps.history.push("/" + searchPath.replace("?","")); } else{ /*.... originally Home event */ }

Ahora, en lugar de llamar a / joblist en url, puede solicitar /? Joblist, y el Componente redirigirá automáticamente la solicitud a / joblist (tome nota del signo de interrogación adicional en la ruta)


Tuve el mismo problema y this solución funcionó para nosotros.

Antecedentes:

Estamos alojando múltiples aplicaciones en el mismo servidor. Cuando actualizaríamos el servidor no entendería dónde buscar nuestro índice en la carpeta dist para esa aplicación en particular. El enlace anterior lo llevará a lo que funcionó para nosotros ... Espero que esto ayude, ya que hemos dedicado muchas horas a encontrar una solución para nuestras necesidades.

Estamos usando:

webpack.config.js /* eslint-disable */ const path = require(''path''); const webpack = require(''webpack''); const HtmlWebpackPlugin = require(''html-webpack-plugin''); const babelPolyfill = require(''babel-polyfill''); const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({ template: __dirname + ''/app/views/index.html'', filename: ''index.html'', inject: ''body'' }); module.exports = { entry: [ ''babel-polyfill'', ''./app/index.js'' ], output: { path: __dirname + ''/dist/your_app_name_here'', filename: ''index_bundle.js'' }, module: { rules: [{ test: //.js$/, loader: ''babel-loader'', query : { presets : ["env", "react", "stage-1"] }, exclude: /node_modules/ }] }, plugins: [HTMLWebpackPluginConfig] }

my webpack.config.js

index.js import React from ''react'' import ReactDOM from ''react-dom'' import Routes from ''./Routes'' import { Provider } from ''react-redux'' import { createHistory } from ''history'' import { useRouterHistory } from ''react-router'' import configureStore from ''./store/configureStore'' import { syncHistoryWithStore } from ''react-router-redux'' import { persistStore } from ''redux-persist'' const store = configureStore(); const browserHistory = useRouterHistory(createHistory) ({ basename: ''/your_app_name_here'' }) const history = syncHistoryWithStore(browserHistory, store) persistStore(store, {blacklist: [''routing'']}, () => { console.log(''rehydration complete'') }) // persistStore(store).purge() ReactDOM.render( <Provider store={store}> <div> <Routes history={history} /> </div> </Provider>, document.getElementById(''mount'') )

my index.js

var express = require(''express''); var app = express(); app.use(express.static(__dirname + ''/dist'')); // app.use(express.static(__dirname + ''/app/assets'')); app.set(''views'', __dirname + ''/dist/your_app_name_here''); app.engine(''html'', require(''ejs'').renderFile); app.set(''view engine'', ''html''); app.get(''/*'', function (req, res) { res.render(''index''); }); app.listen(8081, function () { console.log(''MD listening on port 8081!''); });

my app.js

class App extends Component { render() { return ( <Router history={browserHistory}> <div> <Root> <Switch> <Route exact path={"/"} component={Home} /> <Route path={"/home"} component={Home} /> <Route path={"/createnewproject"} component={CreateNewProject} /> <Route path={"/projects"} component={Projects} /> <Route path="*" component={NotFoundRoute} /> </Switch> </Root> </div> </Router> ) } } render (<App />, window.document.getElementById("app"));


Agregue esto a webpack.congif.js

// app.js import { BrowserRouter as Router } from ''react-router-dom'' const App = () { render() { return ( <Router> // your routes here </Router> ) } }


El Webpack Dev Server tiene una opción para habilitar esto. Abra package.json y agregue --history-api-fallback . Estas soluciones me funcionaron.

react-router-tutorial


En su head index.html, agregue lo siguiente:

<base href="/"> <!-- This must come before the css and javascripts -->

Luego, cuando se ejecuta con el servidor webpack dev, use este comando.

webpack-dev-server --mode development --hot --inline --content-base=dist --history-api-fallback

--history-api-fallback es la parte importante



Este tema es un poco antiguo y está resuelto, pero me gustaría sugerirle una solución simple, clara y mejor. Funciona si usas un servidor web.

Cada servidor web tiene la capacidad de redirigir al usuario a una página de error en el caso de http 404. Para resolver este problema, debe redirigir al usuario a la página de índice.

Si utiliza el servidor base Java (tomcat o cualquier servidor de aplicaciones java), la solución podría ser la siguiente:

web.xml:

<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />

Ejemplo:

  • OBTENGA http://example.com/about
  • El servidor web arroja http 404 porque esta página no existe en el lado del servidor
  • la configuración de la página de error le dice al servidor que envía la página index.jsp al usuario
  • entonces JS hará el resto del trabajo en el lado del cliente porque la url en el lado del cliente todavía es http://example.com/about .

Eso es todo, no más necesidades mágicas :)


Esto puede resolver tu problema

También enfrenté el mismo problema en la aplicación ReactJS en modo Producción. Aquí está la 2 solución al problema.

1.Cambie el historial de enrutamiento a "hashHistory" en lugar de browserHistory en lugar de

<Router history={hashHistory} > <Route path="/home" component={Home} /> <Route path="/aboutus" component={AboutUs} /> </Router>

Ahora compila la aplicación usando el comando

sudo npm run build

Luego coloque la carpeta de compilación en su carpeta var / www /. Ahora la aplicación está funcionando bien con la adición de la etiqueta # en todas y cada una de las URL. me gusta

localhost / # / home localhost / # / aboutus

Solución 2: Sin la etiqueta # usando browserHistory,

Establezca su historial = {browserHistory} en su enrutador, ahora compílelo usando sudo npm run build.

Debe crear el archivo "conf" para resolver la página 404 no encontrada, el archivo conf debería ser así.

abre tu terminal escribe los siguientes comandos

cd / etc / apache2 / sites-available ls nano sample.conf Agregue el contenido a continuación.

<VirtualHost *:80> ServerAdmin [email protected] ServerName 0.0.0.0 ServerAlias 0.0.0.0 DocumentRoot /var/www/html/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory "/var/www/html/"> Options Indexes FollowSymLinks AllowOverride all Require all granted </Directory> </VirtualHost>

Ahora debe habilitar el archivo sample.conf utilizando el siguiente comando

cd /etc/apache2/sites-available sudo a2ensite sample.conf

luego le pedirá que vuelva a cargar el servidor apache, utilizando el servicio sudo apache2 reload o restart

luego abra su carpeta localhost / build y agregue el archivo .htaccess con el contenido de abajo.

RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^.*$ / [L,QSA]

Ahora la aplicación funciona normalmente.

Nota: cambie 0.0.0.0 ip a su dirección IP local.

Si tiene alguna duda al respecto, no dude en hacer un comentario.

Espero que sea útil para los demás.


Intente agregar el archivo ".htaccess" dentro de la carpeta pública con el siguiente código.

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- WELCOME FILE LIST --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- ERROR PAGES DEFINITION --> <error-page> <error-code>404</error-code> <location>/index.jsp</location> </error-page> </web-app>


Las respuestas aquí son extremadamente útiles, lo que funcionó para mí fue configurar mi servidor Webpack para esperar las rutas.

devServer: { historyApiFallback: true, contentBase: ''./'', hot: true },

El historyApiFallback es lo que solucionó este problema para mí. Ahora el enrutamiento funciona correctamente y puedo actualizar la página o escribir la URL directamente. No necesita preocuparse por las soluciones en su servidor de nodo. Esta respuesta obviamente solo funciona si estás usando webpack.

EDITAR: vea mi respuesta aquí para obtener una razón más detallada de por qué esto es necesario: https://.com/a/37622953/5217568


Para usuarios de React Router V4 :

Si intenta resolver este problema mediante la técnica Hash History mencionada en otras respuestas, tenga en cuenta que

<Router history={hashHistory} >

no funciona en V4, utilice HashRouter en HashRouter lugar:

RewriteBase / RewriteRule ^index/.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L]

Referencia: HashRouter


Puede cambiar su htaccess e insertar esto:

import { HashRouter } from ''react-router-dom'' <HashRouter> <App/> </HashRouter>

Estoy usando react: "^15.3.2" , react-router: "^3.0.0" , history: "^4.3.0" ,


Se puede llamar al enrutador de dos maneras diferentes, dependiendo de si la navegación se produce en el cliente o en el servidor. Lo tiene configurado para la operación del lado del cliente. El parámetro clave es el segundo del método de ejecución , la ubicación.

Cuando usa el componente React Router Link, bloquea la navegación del navegador y llama a la transición a para hacer una navegación del lado del cliente. Está utilizando HistoryLocation, por lo que utiliza la API de historial HTML5 para completar la ilusión de navegación simulando la nueva URL en la barra de direcciones. Si está utilizando navegadores antiguos, esto no funcionará. Debería usar el componente HashLocation.

Cuando presiona actualizar, omite todo el código React y React Router. El servidor recibe la solicitud de /joblist y debe devolver algo. En el servidor, debe pasar la ruta solicitada al método de run para que presente la vista correcta. Puede usar el mismo mapa de ruta, pero probablemente necesitará una llamada diferente a Router.run . Como señala Charles, puede usar la reescritura de URL para manejar esto. Otra opción es usar un servidor node.js para manejar todas las solicitudes y pasar el valor de la ruta como argumento de ubicación.

En express, por ejemplo, podría verse así:

var app = express(); app.get(''*'', function (req, res) { // This wildcard method handles all requests Router.run(routes, req.path, function (Handler, state) { var element = React.createElement(Handler); var html = React.renderToString(element); res.render(''main'', { content: html }); }); });

Tenga en cuenta que la ruta de solicitud se pasa para run . Para hacer esto, necesitará tener un motor de vista del lado del servidor al que pueda pasar el HTML renderizado. Hay una serie de otras consideraciones al usar renderToString y al ejecutar React en el servidor. Una vez que la página se procesa en el servidor, cuando su aplicación se carga en el cliente, se volverá a procesar, actualizando el HTML procesado del lado del servidor según sea necesario.


Si aloja su aplicación de reacción en IIS, simplemente agregue un archivo web.config que contenga:

RewriteEngine On RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d RewriteRule ^ - [L] RewriteRule ^ /index.html [L]

Esto le indicará al servidor IIS que devuelva la página principal al cliente en lugar del error 404 y no es necesario usar el historial de hash.


Si tiene una copia de seguridad de su index.html, asegúrese de que en su archivo index.html tenga esto:

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <httpErrors errorMode="Custom" existingResponse="Replace"> <remove statusCode="404" subStatusCode="-1" /> <error statusCode="404" path="/" responseMode="ExecuteURL" /> </httpErrors> </system.webServer> </configuration>

Esto puede diferir de un proyecto a otro.


Todavía no estoy usando el renderizado del lado del servidor, pero me encontré con el mismo problema que el OP donde Link parecía funcionar bien la mayor parte del tiempo pero fallaba cuando tenía un parámetro. Documentaré mi solución aquí para ver si ayuda a alguien.

Mi jsx principal contiene esto:

{ "hosting": { "rewrites": [{ "source":"**", "destination": "/index.html" }] } }

Esto funciona bien para el primer enlace coincidente, pero cuando: id cambia en las expresiones <Link> anidadas en la página de detalles de ese modelo, la url cambia en la barra del navegador pero el contenido de la página no cambió inicialmente para reflejar el modelo vinculado.

El problema era que había usado props.params.id para configurar el modelo en componentDidMount . El componente solo se monta una vez, por lo que esto significa que el primer modelo es el que se pega en la página y los enlaces posteriores cambian los accesorios, pero dejan la página sin cambios.

Establecer el modelo en el estado del componente tanto en componentDidMount como en componentWillReceiveProps (donde se basa en los siguientes accesorios) resuelve el problema y el contenido de la página cambia para reflejar el modelo deseado.


Utilicé create-react-app para hacer un sitio web en este momento y tuve el mismo problema presentado aquí. Uso BrowserRouting del BrowserRouting react-router-dom . Estoy ejecutando en un servidor Nginx y lo que me resolvió fue agregar lo siguiente a /etc/nginx/yourconfig.conf

location / { if (!-e $request_filename){ rewrite ^(.*)$ /index.html break; } }

Lo que corresponde a agregar lo siguiente al .htaccess en caso de que esté ejecutando Appache

Options -MultiViews RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.html [QSA,L]

Esta también parece ser la solución sugerida por Facebook y se puede encontrar here


En caso de que alguien esté buscando una solución en React JS SPA con Laravel. La respuesta aceptada es la mejor explicación de por qué ocurren tales problemas. Como ya se explicó, debe configurar tanto el lado del cliente como el del servidor. En su plantilla Blade, incluya el archivo incluido js, ​​asegúrese de usarlo URL facade así

<script src="{{ URL::to(''js/user/spa.js'') }}"></script>

En sus rutas, asegúrese de agregar esto al punto final principal donde está la plantilla de la hoja. Por ejemplo,

Route::get(''/setting-alerts'', function () { return view(''user.set-alerts''); });

Lo anterior es el punto final principal para la plantilla de la hoja. Ahora agregue una ruta opcional también,

Route::get(''/setting-alerts/{spa?}'', function () { return view(''user.set-alerts''); });

El problema que ocurre es que primero se carga la plantilla de la cuchilla, luego el enrutador de reacción. Entonces, cuando está cargando ''/setting-alerts'' , carga el html y el js. Pero cuando carga ''/setting-alerts/about'' , primero se carga en el lado del servidor. Como en el lado del servidor, no hay nada en esta ubicación, devuelve no encontrado. Cuando tiene ese enrutador opcional, carga la misma página y también se carga el enrutador de reacción, luego el cargador de reacción decide qué componente mostrar. Espero que esto ayude.


Pila de producción: React, React Router v4, BrowswerRouter, Express, Nginx

1) User BrowserRouter para urls bonitas

// server.js app.get(''/*'', function(req, res) { res.sendFile(path.join(__dirname, ''path/to/your/index.html''), function(err) { if (err) { res.status(500).send(err) } }) })

2) Agregue index.html a todas las solicitudes desconocidas utilizando /*

location / { try_files $uri /index.html; }

3) paquete webpack con webpack -p

4) ejecute nodemon server.js o node server.js

EDITAR: es posible que desee dejar que nginx maneje esto en el bloque del servidor y no tenga en cuenta el paso 2:

devServer: { historyApiFallback: true }


Si aloja una aplicación de reacción a través de AWS Static S3 Hosting y CloudFront

Este problema se presentó cuando CloudFront respondió con un mensaje 403 de acceso denegado porque esperaba que / some / other / path existiera en mi carpeta S3, pero esa ruta solo existe internamente en el enrutamiento de React con react-router.

La solución fue configurar una regla de páginas de error de distribución. Vaya a la configuración de CloudFront y elija su distribución. A continuación, vaya a la pestaña "Páginas de error". Haga clic en "Crear respuesta de error personalizada" y agregue una entrada para 403 ya que ese es el código de estado de error que obtenemos. Establezca la Ruta de la página de respuesta en /index.html y el código de estado en 200. El resultado final me sorprende con su simplicidad. La página de índice se sirve, pero la URL se conserva en el navegador, por lo que una vez que se carga la aplicación de reacción, detecta la ruta de la URL y navega hacia la ruta deseada.

Error Páginas 403 Regla


Si está utilizando la aplicación Create React:

Sin embargo, hay un gran recorrido por este problema con soluciones para muchas de las principales plataformas de alojamiento que puede encontrar HERE en la página Crear aplicación React. Por ejemplo, uso React Router v4 y Netlify para mi código de interfaz. Todo lo que se necesitó fue agregar 1 archivo a mi carpeta pública ("_redirects") y una línea de código en ese archivo:

/* /index.html 200

Ahora mi sitio web representa correctamente rutas como mysite.com/pricing cuando se ingresa al navegador o cuando alguien presiona actualizar.


Al observar los comentarios sobre la respuesta aceptada y la naturaleza genérica de esta pregunta (''no funciona''), pensé que este podría ser un buen lugar para algunas explicaciones generales sobre los problemas involucrados aquí. Por lo tanto, esta respuesta pretende ser información / elaboración de antecedentes sobre el caso de uso específico del OP. Por favor, tenga paciencia conmigo.

Lado del servidor vs lado del cliente

Lo primero que hay que entender sobre 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 de http://example.com/about al servidor, que inspeccionaba la parte de la ruta de la URL, determinaba que el usuario estaba solicitando la página acerca y luego la enviaba de vuelta 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 JS cargado. Entonces, la primera solicitud siempre será al servidor. Eso devolverá una página que contiene las etiquetas de secuencia de comandos necesarias para cargar React y React Router, etc. Solo cuando se hayan cargado esas secuencias de comandos comienza 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 (hecho posible por la API de historial ), pero no se solicita al servidor esta hecho . En cambio, React Router hace lo suyo en el lado del cliente, determina qué vista de React renderizar y lo representa. Asumiendo que su página acerca de no necesita hacer llamadas REST, ya está hecha. Ha pasado de Inicio a Acerca de nosotros sin que se haya activado ninguna solicitud del servidor.

Básicamente, cuando hace clic en un enlace, se ejecuta un Javascript que manipula la URL en la barra de direcciones, sin causar 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. En otras palabras, ella todavía está en la fase 1 . Todavía no se está ejecutando ningún React Router en su máquina. Por lo tanto, su navegador realizará una solicitud del servidor a http://example.com/about .

Y aquí es donde comienza tu problema. Hasta ahora, podría salirse con la simple colocación de un HTML estático en la raíz web de su servidor. Pero eso daría errores 404 para todas las otras URL cuando se solicite 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.

Combinación de 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 del lado del cliente, debe configurar rutas para ella tanto en el lado del servidor como del lado del cliente. Tiene sentido ¿verdad?

Y aquí es donde comienzan tus elecciones. Las soluciones van desde eludir el problema por completo, a través de una ruta general que devuelve el HTML de arranque, hasta el enfoque isomorfo completo en el que tanto el servidor como el cliente ejecutan el mismo código JS.

.

Evitando el problema por completo: Hash History

Con Hash History en lugar de Browser History , su URL para la página acerca se vería así: http://example.com/#/about La parte después del símbolo hash ( # ) 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 parte #/about y mostrará la página correcta.

Desventajas :

  • URL ''feas''
  • La representació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 sola página con casi ningún contenido.

.

Catch-all

Con este enfoque, sí utiliza el historial del navegador, pero simplemente configura un conjunto en el servidor que envía /* a index.html , lo que le proporciona prácticamente 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 expande en el escenario general al agregar secuencias de comandos específicas para rutas específicas. Puede crear algunos scripts PHP simples para devolver las páginas más importantes de su sitio con contenido incluido, de modo que Googlebot pueda al menos ver lo que hay en su página.

Desventajas :

  • Aún más complejo de configurar
  • Solo buen SEO para esas rutas le das el trato especial
  • Duplicación de código para representar contenido en el servidor y el cliente

.

Isomorfo

¿Qué sucede si utilizamos Node JS como nuestro servidor para poder ejecutar el mismo código JS 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 representación. Este es ''el santo grial'', por así decirlo. El servidor envía exactamente el mismo marcado 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 JS. He experimentado con Java icw Nashorn pero no me funciona. En la práctica, significa principalmente que debe utilizar un servidor basado en Node JS.
  • Muchos problemas ambientales difíciles (uso de la window en el lado del servidor, etc.)
  • Curva de aprendizaje empinada

.

¿Cuál debería usar?

Elija el que pueda salirse con la suya. Personalmente, creo que el conjunto es lo suficientemente simple como para configurarlo, 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 su plataforma de servidor, definitivamente investigaría 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 para el problema.

Básicamente, para mí, ese sería el factor decisivo. Si mi servidor se ejecuta en el Nodo JS, me volvería isomorfo; de lo contrario, optaría por la solución Catch-all y solo 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 isomorfo (también llamado ''universal'') con React, hay algunos buenos tutoriales sobre el tema:

Además, para comenzar, te recomiendo mirar 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 construir una aplicación completa). Comience mirando el publicado por el propio Facebook:

O elija uno de los muchos de la comunidad. Hay un buen sitio ahora que intenta indexarlos a todos:

Empecé con estos:

Actualmente estoy usando una versión casera de renderizado universal inspirada en los dos kits de inicio anteriores, pero ahora están desactualizados.

¡Buena suerte con tu búsqueda!