Las URL de React-router no funcionan al actualizar o escribir manualmente

918

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 adentro localhost/joblisty 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/#/joblisty funcionaban perfectamente bien. Pero no me gusta este tipo de URL, así que tratando de borrar eso #, escribí:

Router.run(routes, Router.HistoryLocation, function (Handler) {
 React.render(<Handler/>, document.body);
});

Este problema no pasa con localhost/, este siempre devuelve lo que quiero.

EDITAR: esta aplicación es de una sola página, por lo /joblistque 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);
});
5
  • a menos que use htaccess para cargar su página principal de gira y le diga a su enrutador que use location.pathname, no funcionará ...
    CJT3
    20/01/15 a las 16:44
  • ¿Cómo borraste ese #símbolo? ¡Gracias!
    SudoPlz
    6/06/2015 a las 11:57
  • 9
    Si aloja su aplicación de reacción en un bucket de S3, simplemente puede configurar el documento de error en index.html. Esto asegurará que index.htmlsea ​​acertado pase lo que pase. 30/07/2016 a las 18:49
  • En mi caso, funciona bien en Windows pero no en Linux. 4 dic 2017 a las 19:05
  • Esta es la referencia que ayudó a resolver mi problema: github.com/facebook/create-react-app/blob/master/packages/… 9/07/18 a las 22:56
1443

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í. Entonces, esta respuesta está pensada como información de fondo / elaboración sobre el caso de uso específico del OP. Por favor, tenga paciencia conmigo.

Del lado del servidor vs del 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 http://example.com/aboutal 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 JS cargado. Entonces, la primera solicitud siempre será al servidor. Eso luego devolverá una página que contiene las etiquetas de script necesarias para cargar React y React Router, etc. Solo cuando esos scripts se han cargado, 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 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 hacer ninguna llamada REST, ya está hecho. Ha realizado la transición de Inicio a Acerca de nosotros sin que se haya disparado ninguna solicitud del servidor.

Entonces, básicamente, cuando haces 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, todavía está en la fase 1 . Todavía no se está ejecutando ningún React Router en su máquina. Entonces su navegador hará una solicitud al servidorhttp://example.com/about .

Y aquí es donde comienza tu problema. Hasta ahora, podía salirse con la suya simplemente colocando un HTML estático en la raíz web de su servidor. Pero eso daría 404errores 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 usted haga que su servidor las entienda.

Combinando el enrutamiento del lado del servidor y del cliente

Si desea que la http://example.com/aboutURL funcione tanto en el lado del servidor como en el del cliente, debe configurar rutas para ella tanto en el lado del servidor como en el del cliente. Tiene sentido, ¿verdad?

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

.

Evitando el problema por completo: historial de hash

Con Hash History en lugar del Browser History , su URL para la página acerca de 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 #/aboutpieza 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 sin apenas contenido.

.

Atrapar todo

Con este enfoque, se hace Historia uso del navegador, pero sólo hay que montar un cajón de sastre en el servidor que envía /*a index.html, efectivamente le da la misma situación que con Hash Historia. 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 es un buen SEO

.

Híbrido

En el enfoque híbrido, amplía el escenario general al agregar scripts específicos 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 aquellas rutas a las que le das el trato especial
  • Código duplicado para renderizar contenido en servidor y cliente.

.

Isomorfo

¿Qué pasa si usamos 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 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 JS. He experimentado con Java icw Nashorn pero no me funciona. En la práctica, principalmente significa que debe usar un servidor basado en Node JS.
  • Muchos problemas ambientales complicados (uso windowen el lado del servidor, etc.)
  • Curva de aprendizaje pronunciada

.

¿Cuál debo usar?

Elija el que pueda salirse con la suya. Personalmente, creo que el catch-all es lo suficientemente simple 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 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, es una solución muy elegante al problema.

Entonces, básicamente, para mí, ese sería el factor decisivo. Si mi servidor se ejecuta en Node JS, me volvería isomorfo; de lo contrario, optaría por la solución Catch-all y simplemente la expandiría (solución híbrida) a medida que avanza 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, hay algunos buenos tutoriales sobre el tema:

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

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

Comencé con estos:

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

¡Buena suerte con tu búsqueda!

38
  • 2
    ¡Gran publicación Stijn! ¿Recomendaría ir con un kit de inicio para una aplicación de reacción isomorfa? Si es así, ¿podría dar un ejemplo de uno que prefiera?
    Chris
    29/04/2016 a las 9:40
  • 2
    @ Paulos3000 Depende del servidor que esté utilizando. Básicamente, usted define una ruta /*y la hace responder con su página HTML. Lo complicado aquí es asegurarse de no interceptar solicitudes para los archivos .js y .css con esta ruta. 30 oct 2016 a las 19:27
  • 2
    @ Paulos3000 Vea aquí algunas preguntas relacionadas: para Apache / php , para Express / js , para J2E / Java . 30 oct 2016 a las 19:35
  • 2
    @Stijn de Witt Esta es una gran aclaración y una buena respuesta sobre este tema. Sin embargo, ¿cuáles son las opciones cuando su aplicación podría ser servida dentro de un subdirectorio (por iis, por ejemplo)? Es decir: dominio / nombre de la aplicación / nombre de la ruta o dominio / nombre de la aplicación / subcarpeta / nombre de la ruta 19 de marzo de 2017 a las 12:51
  • 5
    @LeonGaban Parece que desde que se escribió esta respuesta, React Router cambió su implementación. Ahora tienen diferentes instancias de enrutador para los diferentes historiales y hacen la configuración del historial en segundo plano. Los principios básicos siguen siendo los mismos. 17 de julio de 2017 a las 13:03
156

Las respuestas aquí son todas 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 hay necesidad de preocuparse por soluciones alternativas en su servidor de nodo. Obviamente, esta respuesta solo funciona si está usando webpack.

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

6
  • 24
    Tenga en cuenta que el equipo de Webpack recomienda no utilizar el servidor de desarrollo en producción. 13/06/2016 a las 17:47
  • 5
    Para propósitos de desarrollo genérico, esta es la mejor solución. historyApiFallbackes suficiente. Como para todas las otras opciones, también se puede configurar desde CLI con la bandera --history-api-fallback. 27/10/2016 a las 18:28
  • 2
    @Kunok No lo hace. Esta es una solución rápida para el desarrollo, pero aún tendrá que pensar en algo para la producción. 30 de mayo de 2017 a las 22:01
  • contentBase: ': /' porque se puede acceder a los archivos de su aplicación desde la URL
    Nezih
    21 feb 2018 a las 11:10
  • 1
    Funciona para React 17. Gracias 26 de junio a las 11:29
145

Puede cambiar su .htaccessarchivo e insertar esto:

<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 el Catch-all y es probablemente la forma más fácil de comenzar.

10
  • 5
    ¡Esto funciona bien! y el más fácil si no desea reestructurar su aplicación 13/02/18 a las 7:41
  • 7
    No olvide RewriteEngine On como la primera línea 31 oct 2018 a las 22:50
  • 25
    Tenga en cuenta que esta respuesta se refiere a la configuración en un servidor Apache. Esto no es parte de una aplicación React. 16/07/19 a las 22:52
  • No entendí las respuestas anteriores. Ninguno de los tutoriales dijo que mis enlaces no funcionarían en vivo. Sin embargo, este simple archivo htaccess funcionó. Gracias 26 mar.20 a las 18:33
  • Esto también funciona para la exportación estática next.js. Como el tomcat no es similar al nodo, necesitamos esta configuración adicional para la exportación estática next.js. 4 abr.20 a las 2:15
81

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 HashRouteren su lugar:

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

Referencia: HashRouter

2
  • ¿Podría darnos algún detalle sobre por qué HashRouter soluciona este problema? El enlace que proporcionaste no me lo explica. Además, ¿hay alguna forma de ocultar el hash en la ruta? Estaba usando el BrowserRouter pero encontré este problema 404 con él. 7 de junio de 2020 a las 0:15
  • Estaba usando el enrutador del navegador y estaba causando un error 404 en la actualización, pero luego reemplacé el enrutador del navegador con un enrutador hash y no funciona bien. Gracias 31 jul.20 a las 18:29
50

Usé create-react-app para hacer un sitio web hace un momento y tuve el mismo problema presentado aquí. Yo uso BrowserRoutingdel react-router-dompaquete. Estoy corriendo 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 .htaccessen 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 los propios Facebook y se puede encontrar aquí.

7
  • 3
    Vaya, una solución tan simple para nginx; funciona como un encanto, como nuevo usuario de nginx. Simplemente copie y pegue y listo. +1 para vincular a la documentación oficial de fb. Camino a seguir. 13/01/19 a las 19:15
  • Para el registro: estoy usando una instancia de AWS con nginx y una aplicación angular. Esto funciona. 3 jun 19 a las 14:30
  • 1
    me salvas. Estaba tratando de solucionar mi problema de ayer. Me cansé de un par de soluciones, pero fallé. finalmente me ayudaste a resolver este problema del enrutador. ah muchas gracias hermano 22 de septiembre de 2019 a las 1:59
  • ¿Se necesita algo diferente para "react": "^ 16.8.6", "react-router": "^ 5.0.1"? Probé estas soluciones (tanto nginx como apache) y no funcionan. 21/10/19 a las 12:36
  • Como Facebook no ha cambiado su documentación con respecto a esto, solo puedo asumir que el procedimiento es el mismo. Aunque no lo he probado en un tiempo.
    Aidin
    21/10/19 a las 13:51
35

En su index.html head, agregue lo siguiente:

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

Luego, cuando se ejecute con el servidor de desarrollo webpack, use este comando.

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

--history-api-fallback es la parte importante

5
  • 1
    ¡Esto funcionó muy bien! ¿Algún enlace para leer un poco más sobre cómo obtuvo / encontró esa solución?
    justDan
    26/06/18 a las 13:56
  • 1
    Lo siento hermano. Lo encontré a través de la técnica probada y verdadera de prueba y error. 30/06/18 a las 10:31
  • Vale la pena mencionar que si está usando un href base que no lo es, /entonces HashRouterno funcionará (si está usando enrutamiento hash) 17/01/19 a las 16:06
  • La etiqueta <base href = "/"> lo hizo por mí. Gracias por esto. El servidor de desarrollo de Webpack seguía intentando tomar el paquete de la ruta / <bundle> y fallaba. 26 mar 2019 a las 7:30
  • Estoy usando el modo React.js + Webpack. Agregué el parámetro --history-api-fallback en el archivo package.json. Entonces, la actualización de la página funciona correctamente. Cada vez que cambio el código, la página web se actualiza automáticamente. `` `" scripts ": {" start ":" rimraf build && cross-env NODE_ENV = 'desarrollo' webpack --mode development && cross-env NODE_ENV = desarrollo webpack-dev-server --history-api-fallback ", ...} `` ` 12/08/20 a las 21:49
32

El enrutador se puede llamar de dos formas diferentes, dependiendo de si la navegación se realiza 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 para hacer una navegación del lado del cliente. Estás usando HistoryLocation, por lo que usa 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 más antiguos, esto no funcionará. Debería utilizar el componente HashLocation.

Cuando presiona actualizar, omite todo el código React y React Router. El servidor recibe la solicitud /joblisty debe devolver algo. En el servidor, debe pasar la ruta solicitada al runmétodo para que pueda representar la vista correcta. Puede usar el mismo mapa de ruta, pero probablemente necesite 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 se está pasando la ruta de la solicitud 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 sobre el uso renderToStringy la ejecución de React en el servidor. Una vez que la página se renderiza en el servidor, cuando su aplicación se carga en el cliente, se volverá a renderizar, actualizando el HTML renderizado del lado del servidor según sea necesario.

10
  • 2
    disculpe Disculpe, ¿podría explicar por favor la siguiente declaración "cuando presiona actualizar, omite todo el código React y React Router"? ¿Por que sucede?
    VB_
    8 de septiembre de 2015 a las 11:24
  • El enrutador React se usa normalmente para manejar diferentes 'rutas' solo dentro del navegador. Hay dos formas típicas de hacer esto: la ruta de hash de estilo antiguo y la API de historial más nueva. Una actualización del navegador hará una solicitud al servidor, que omitirá el código del enrutador de reacción del lado del cliente. Deberá manejar la ruta en el servidor (pero solo si está utilizando la API de historial). Puede usar el enrutador react para esto, pero deberá hacer algo similar a lo que describí anteriormente.
    Todd
    9 de septiembre de 2015 a las 16:26
  • Entendido. Pero, ¿cómo ser si el servidor está en un lenguaje que no es JS (digamos Java)?
    VB_
    9 de septiembre de 2015 a las 18:44
  • 2
    lo siento ... ¿quiere decir que necesita un servidor exprés para representar una ruta que no es "root"? Primero me sorprendió que la definición del isomorfismo no incluyera la búsqueda de datos en su concepto (las cosas son desesperadamente complejas si desea representar la vista CON el lado del servidor de datos, aunque sería una necesidad obvia de SEO, y el isomorfismo lo afirma). Ahora estoy como "WTF reacciona", en serio ... Corrígeme si me equivoco, ¿ember / angular / backbone requiere algo del servidor para representar una ruta? Realmente no entiendo este requisito inflado para usar rutas
    Ben
    17/10/15 a las 8:41
  • 1
    ¿Significa que la actualización en react-router no funciona si mi aplicación de reacción no es isomórfica?
    Matt
    7 dic.15 a las 14:50
27

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 AQUÍ en la página Create React App. Por ejemplo, uso React Router v4 y Netlify para mi código de interfaz. Todo lo que 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 muestra correctamente rutas como mysite.com/pricing cuando se ingresa en el navegador o cuando alguien presiona actualizar.

1
26

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 Acceso denegado porque esperaba que existiera / alguna / otra / ruta en mi carpeta S3, pero esa ruta solo existe internamente en el enrutamiento de React con react-router.

La solución fue establecer una regla de distribución de páginas de error. 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. Se sirve la página de índice, 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 a la ruta deseada.

Regla 403 de las páginas de error

7
  • 2
    Esto es exactamente lo que necesitaba. Gracias. 19/09/19 a las 17:40
  • Entonces ... ¿todas tus URL funcionan, pero devuelven el código de estado 403? No es correcto. Los códigos de estado esperados deben estar en el rango 2xx. 21/10/19 a las 18:35
  • @StijndeWitt No estoy seguro de que lo entiendas correctamente. CloudFront se encargará de todo: el cliente no verá ningún código de estado 403. El redireccionamiento ocurre en el lado del servidor, muestra la página de índice, mantiene la URL y, como resultado, proporciona la ruta correcta.
    th3morg
    22/10/19 a las 1:17
  • 1
    gracias por esto @ th3morg. ¿Esta configuración también funciona para rutas de varios niveles? Funciona muy bien para mí si hay alguna ruta en el nivel raíz, como dominio / registro, dominio / inicio de sesión, dominio / <documentId>, pero no funciona para rutas de varios niveles, como dominio / documento / <documentId>.
    Pargles
    3 feb.20 a las 13:58
  • 2
    ¡Oh, hermoso ser! ¡Necesitaba configurarlo para una respuesta 404 y funcionó a las mil maravillas! 6 jul.20 a las 19:12
23

Esto puede resolver tu problema.

También enfrenté el mismo problema en la aplicación ReactJS en el modo de 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 construya 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. igual que

localhost / # / home localhost / # / aboutus

Solución 2: sin etiqueta # usando browserHistory,

Configure su historial = {browserHistory} en su enrutador, ahora constrúyalo usando sudo npm run build.

Necesita 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 necesita habilitar el archivo sample.conf usando el siguiente comando

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

luego le pedirá que vuelva a cargar el servidor apache, usando el servicio sudo apache2 recargar o reiniciar

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 con normalidad.

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 de ayuda para otros.

4
  • ¿Funcionará la primera solución "react-router-dom": "^5.1.2"?, estoy usando<BrowserRouter>
    151291
    13/12/19 a las 5:31
  • .htaccess me lo arregló. 3 de febrero a las 10:17
  • dónde, obtendré el browserHistory, en la solución 2.
    Sushil
    6 feb a las 13:53
  • agregando solo el archivo .htaccess en la carpeta de compilación arreglada para mí, gracias hombre 19 de mayo a las 4:24
19

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

<?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 le indicará al servidor IIS que devuelva la página principal al cliente en lugar del error 404 y no es necesario utilizar el historial de hash.

0
17

Webpack Dev Server tiene una opción para habilitar esto. Abre package.jsony agrega --history-api-fallback. Esta solución funcionó para mí.

reaccionar-enrutador-tutorial

1
  • 10
    Está bien, webpack-dev-serverpero ¿cómo soluciono esto para la versión de producción?
    Hussain
    15/08/18 a las 9:57
14

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

1) User BrowserRouter para URL bonitas

// app.js

import { BrowserRouter as Router } from 'react-router-dom'

const App = () {
  render() {
    return (
        <Router>
           // your routes here
        </Router>
    )
  }
}

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

// 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)
    }
  })
})

3) paquete webpack con webpack -p

4) correr nodemon server.jsonode server.js

EDITAR: es posible que desee dejar que nginx maneje esto en el bloque del servidor e ignorar el paso 2:

location / {
    try_files $uri /index.html;
}
4
  • obteniendo camino de indefinido
    Goutham
    10 de agosto de 2017 a las 8:33
  • @Goutham En la parte superior de su archivo server.js agregue import path from 'pathoconst path = require('path') 10 de agosto de 2017 a las 14:10
  • el paso 2 (atrapar todo con /*) acaba de salvarme el día. ¡Gracias! :)
    Atlas7
    21/11/2017 a las 23:39
  • Esto funciona, para las personas que usan redux y están preocupadas por un enrutador conectado, vea este ejemplo: github.com/supasate/connected-react-router/tree/master/examples/… 16/04/18 a las 15:35
14

Agregue esto a webpack.config.js:

devServer: {
    historyApiFallback: true
}
1
  • 1
    Eso es genial para los desarrolladores, pero no ayuda con las compilaciones de producción.
    KFunk
    5 de mayo de 2020 a las 20:55
7

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

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

RewriteRule ^ /index.html [L]  
1
  • Gracias, esto fue lo que funcionó para mí en Fedora 28 con apache. Ninguna de las reglas de reescritura anteriores ni las de la página de CRA funcionaron para mí. Los agregué a la configuración del host virtual en lugar de en un archivo .htaccess separado.
    boerre
    25 nov 2019 a las 14:44
7

Si está usando 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:

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

Espero que esto le ahorre a otra persona un montón de frustración y pérdida de tiempo.

Codificación feliz ...

Más lecturas 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)"

1
6

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

<script>
  System.config({ baseURL: '/' });
</script>

Esto puede diferir de un proyecto a otro.

1
  • 3
    Agregue esto a su html head: <base href = "/"> 2 de abril de 2018 a las 8:53
5

Para aquellos que usan IIS 10, esto es lo que deben hacer para corregir esto. Asegúrese de que está utilizando browserHistory con esto. Como 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:

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"));

Dado que el problema es que IIS recibe una solicitud de los navegadores del cliente, interpretará la URL como si estuviera solicitando una página y 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 / la 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ámbiela a "Ejecutar una URL en este sitio" y agregue el valor de barra "/" a la URL.

Y ahora funcionará bien.

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Espero que ayude. :-)

2
  • la mejor solución después de 3-4 horas de búsqueda. muchas gracias :)
    KMR
    17 sep.20 a las 20:24
  • Dios te bendiga hombre 1 de junio a las 6:55
4

Encontré la solución para mi SPA con enrutador react (Apache). Solo agregue .htaccess

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

fuente: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa7136042

4

puedes intentar leer todo esto aunque no es mío:

https://www.andreasreiterer.at/fix-browserrouter-on-apache/

Arreglando el enrutamiento de la aplicación A continuación, le mostramos cómo arreglar finalmente el enrutamiento. Para decirle a Apache que redirija las solicitudes a index.html donde vive nuestra aplicación, tenemos que modificar el archivo .htaccess. Si aún no existe ese archivo en la carpeta de su aplicación, simplemente créelo.

Luego asegúrese de poner esas 4 líneas que mágicamente harán que su enrutamiento funcione.

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

Después de colocar ese archivo .htaccess en el mismo directorio que index.html, Apache redirigirá cada nueva solicitud directamente a su aplicación.

Bonificación: implementar la aplicación React en un subdirectorio

Si está implementando su aplicación en un subdirectorio, por lo que es accesible, por ejemplo, a través de https://myapp.com/the-app , pronto notará que hay otro problema. Cada clic en una nueva ruta transformará la URL en algo como https://myapp.com/route-abc , que se romperá nuevamente después de una recarga. Pero hay una solución simple para eso:

BrowserRouter tiene un prop llamado basename donde puede especificar la ruta de su subdirectorio:

A partir de ahora, cada Me gusta / contactos de Ruta dará como resultado una URL como http://myapp.com/the-app/contacts .

3
  • 1
    Esta es una solución muy simple para aquellos que desean ejecutar su CRA desde un directorio diferente. Estoy usando, react-router-domasí que tuve que incluirlo basenameen el <BrowserRouter />. Pero esta sencilla solución le ahorrará mucho tiempo. ¡Gracias por esta contribución! 17/09/20 a las 19:32
  • Gracias. Tu solución me ahorra tiempo. :) 18/11/20 a las 8:14
  • Me alegro de haber podido ayudar .. :) 9 dic.20 a las 14:50
3

Todavía no estoy usando la representación del lado del servidor, pero tengo 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:

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

Esto funciona bien para el primer enlace coincidente, pero cuando: id cambia en <Link>expresiones 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.idpara configurar el modelo 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 en ambos componentDidMounty 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.

1
  • 1
    Podría ser mejor usar el constructor de componentes (que también tiene acceso a props) iso componentDidMountsi alguna vez desea probar la representación del lado del servidor. Porque componentDidMountsolo se llama en el navegador. Su propósito es hacer cosas con el DOM, como adjuntar oyentes de eventos, bodyetc., que no puede hacer en render. 20/12/2016 a las 18:38
3

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

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

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

web.xml:

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

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íe la página index.jsp al usuario
  • luego JS hará el resto del trabajo en el lado del cliente porque la URL en el lado del cliente sigue siendo http://example.com/about .

Eso es todo, no se necesita más magia :)

2
  • ¡Esto fue asombroso! Estoy usando el servidor Wildfly 10.1 e hice esta actualización en mi archivo web.xml, excepto que tenía la ubicación configurada solo en '/'. Esto se debió a que en mi código de reacción utilicé el historial del navegador como este:const browserHistory = useRouterHistory(createHistory)({ basename: '/<appname>' });
    Chuck L
    1 de junio de 2017 a las 21:40
  • 1
    ¿Estás seguro de que esto no afecta al SEO? Estás dando un estado 404 a las páginas que realmente existen. Es posible que el usuario nunca se dé cuenta de esto, pero los bots prestan mucha atención, de hecho tanta, que no rasparán su página.
    subharb
    15 de diciembre de 2017 a las 7:53
3

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

expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
});
1
  • esta es la solución más simple. tenga en cuenta que esta ruta debe ir después de cualquier otra ruta, ya que es una captura de todos
    dcsan
    14/02/20 a las 4:01
3

Se corrigió el error "no se puede GET / URL" al actualizar o al llamar a la URL directamente.

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

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

El uso también HashRouterfuncionó para mí con Redux , simplemente reemplace:

import {
  Router //replace Router
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <Router history={history}> //replace here saying Router
            <Layout/>
        </Router>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();

para:

import {
  HashRouter //replaced with HashRouter
} from "react-router-dom";

ReactDOM.render(
    <LocaleProvider locale={enUS}>
    <Provider store={Store}>
        <HashRouter history={history}> //replaced with HashRouter
            <Layout/>
        </HashRouter>
    </Provider>
</LocaleProvider>, document.getElementById("app"));
registerServiceWorker();
3

Si está utilizando el comando "create-react-app",

para generar una aplicación de reacción, el package.json debe tener un cambio para ejecutar correctamente la compilación de producción React SPA en un navegador. Abra package.json y agregue el siguiente segmento de código a eso,

"start": "webpack-dev-server --inline --content-base . --history-api-fallback"

Aquí, la parte más importante es "--history-api-fallback" para habilitar la devolución de llamada de la API del historial.

A veces, obtendrá un error 404 si usa Spring o cualquier otra API de back-end. Entonces, en tal situación, necesita tener un controlador en el back-end para reenviar cualquier solicitud (que desee) al archivo index.html para que la maneje react-router. A continuación, se muestra un controlador de ejemplo escrito con spring.

@Controller
public class ForwardingController {
    @RequestMapping("/<any end point name>/{path:[^\\.]+}/**")
    public String forward(HttpServletRequest httpServletRequest) {
        return "forward:/";
    }
}

por ejemplo, si tomamos un punto final REST de API back-end como "abc" (http: // localhost: 8080 / abc / **), cualquier solicitud que llegue a ese punto final se redirigirá a la aplicación de reacción (archivo index.html), y react-router se encargará de las contraseñas.

1
  • También puede agregar múltiples asignaciones como esta: @RequestMapping ({"/ myurl1 / **", "/ myurl2 / **"})
    Craigo
    16 de diciembre de 2020 a las 23:11
2

En caso de que alguien esté aquí 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 lado del servidor. En su plantilla de hoja, incluya el archivo empaquetado js, ​​asegúrese de usarlo URL facadeasí

<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 de la plantilla Blade. 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 hoja, luego se carga 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. Dado que en el lado del servidor, no hay nada en esta ubicación, devuelve no encontrado. Cuando tienes ese enrutador opcional, carga esa 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.

2
  • ¿Es posible cargar en un URI exacto al servidor y luego el servidor realiza una redirección a React? Como ejemplo, cuando cargo /user/{userID}, solo necesito devolver una /uservista HTML universal , traer la ID y llamarla usando AJAX o axios. ¿Es posible hacer eso? ¿Son compatibles con SEO?
    Ryuujo
    22 feb 2019 a las 4:24
  • Utilizo este código para mis SPA con un backend de Laravel: Route::any('{any?}', '[email protected]');coincide con cualquier ruta y lo pasa al SPA 7 de septiembre de 2020 a las 21:00
2

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

    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");
        }
   }

Básicamente, en el lado de MVC, todas las rutas que no coincidan se clasificarán Home/Indexsegún lo especificado en startup.cs. En Indexsu interior es posible obtener la URL de solicitud original y pasarla donde sea necesario.

startup.cs

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

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
4
  • Si la API web está separada de la aplicación, ¿cómo manejará esto? 1 de mayo de 2019 a las 17:18
  • @ dayanrr91 si su proyecto tiene una API web, no necesitará el enrutamiento del lado del servidor de todos modos. Y su enrutador de reacción creo que debería leer la URL y hacer el enrutamiento apropiado. Nada debería bloquearlo
    Elnoor
    1 de mayo de 2019 a las 17:28
  • su comentario es muy apreciado, pero luego tengo una pregunta, acabo de agregar HashRouter, pero ahora cuando ingreso a cualquier URL manualmente, se redirigirá a mi componente de inicio en lugar de redirigir a mi hogar y luego al componente que estaba tratando de entrar, ¿hay alguna solución para eso? 1 de mayo de 2019 a las 17:33
  • @ dayanrr91 no tengo idea realmente, no he probado hashrouter nunca, pero creo que debería haber algo que ver con tu código. La forma en que funciona hashrouter debería ser similar a la del browserrouter. También acabo de probar aquí en esta caja de arena, funciona bien codesandbox.io/s/25okp1mny , prueba la url 25okp1mny.codesandbox.io/#/roster/5
    Elnoor
    1 de mayo de 2019 a las 17:47
2

Si está alojando en IIS; Agregar esto a mi webconfig resolvió mi problema

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

Puede realizar una configuración similar para cualquier otro servidor

2

Para aquellos de ustedes que están aquí porque están tratando de servir una aplicación de reacción desde un directorio virtual de IIS (no la raíz de un sitio web), entonces esto puede ser para ustedes.

Cuando configurar sus redirecciones '/' no funcionará por sí solo, para mí también necesitaba el nombre del directorio virtual allí. Así es como se veía mi configuración web:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <defaultDocument>
            <files>
                <remove value="default.aspx" />
                <remove value="iisstart.htm" />
                <remove value="index.htm" />
                <remove value="Default.asp" />
                <remove value="Default.htm" />
            </files>
        </defaultDocument>
        <rewrite>
            <rules>
                <rule name="React Routes" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/YOURVIRTUALDIRECTORYNAME/" />
                </rule>
            </rules>
        </rewrite>
        <directoryBrowse enabled="false" />
        <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
            <remove statusCode="500" subStatusCode="100" />
            <remove statusCode="500" subStatusCode="-1" />
            <remove statusCode="404" subStatusCode="-1" />
            <remove statusCode="403" subStatusCode="18" />
            <error statusCode="403" subStatusCode="18" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
            <error statusCode="404" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
            <error statusCode="500" prefixLanguageFilePath="" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
            <error statusCode="500" subStatusCode="100" path="/YOURVIRTUALDIRECTORYNAME/" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>

Además del archivo web.config, la aplicación de reacción necesitaba algunos cambios:

en package.json, debe agregar una entrada de 'página de inicio':

{
  "name": "sicon.react.crm",
  "version": "0.1.0",
  "private": true,
  "homepage": "/YOURVIRTUALDIRECTORYNAME/",
  "dependencies": {
...

Agregué el nombre base al objeto del historial de mi navegador que paso al enrutador para obtener acceso al historial:

import  {createBrowserHistory } from 'history';

export default createBrowserHistory({
    //Pass the public URL as the base name for the router basename: process.env.PUBLIC_URL
});

También agregué esta propiedad en mi enrutador React en App.js:

  <Router history={history} basename={process.env.PUBLIC_URL}>

Finalmente, en index.html agregué la siguiente pestaña encima de la etiqueta 'título'

  <base href="%PUBLIC_URL%/">

puede ser que se requieran algunos pasos, pero esto parece haber hecho el trabajo por mí. No sé cómo configurarlo para que se ejecute en la raíz de un sitio o en un directorio virtual sin una recompilación, ya que la página de inicio en el package.jsonno se puede intercambiar después de una compilación que yo sepa.

2
  • 1
    Las últimas dos líneas de código de tu publicación me salvaron. ¡Gracias! basenameen <Router />y <base />en index.html. 28 abr a las 20:56
  • @CraigHowell - ¡Me alegro de haber ayudado! ¡He vuelto a esta publicación para recordarme a mí también! 30 abr a las 7:50