URL-адреса React-router не работают при обновлении или записи вручную

Я использую React-router, и он отлично работает, пока я нажимаю кнопки ссылок, но когда я обновляю свою веб-страницу, она не загружает то, что я хочу.

Например, я нахожусь в localhost/joblist, и все в порядке, потому что я пришел сюда по ссылке. Но если я обновлю веб-страницу, я получу:

Cannot GET /joblist

По умолчанию так не работало. Первоначально у меня были URL-адреса localhost/#/ и localhost/#/joblist, и они работали отлично. Но мне не нравятся такие URL-адреса, поэтому, пытаясь стереть #, я написал:

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

Эта проблема не возникает с localhost/, этот всегда возвращает то, что я хочу.

РЕДАКТИРОВАТЬ: Это одностраничное приложение, поэтому /joblist не нужно ничего запрашивать ни на каком сервере.

EDIT2: весь мой маршрутизатор.

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

person DavidDev    schedule 13.01.2015    source источник
comment
если вы не используете htaccess для загрузки своей основной туристической страницы и не укажете маршрутизатору использовать location.pathname, это не сработает.   -  person CJT3    schedule 20.01.2015
comment
Как вы стерли этот символ #? Спасибо!   -  person SudoPlz    schedule 06.06.2015
comment
Если вы размещаете свое приложение для реагирования в корзине S3, вы можете просто установить для документа с ошибкой значение index.html. Это обеспечит попадание в index.html несмотря ни на что.   -  person Trevor Hutto    schedule 30.07.2016
comment
В моем случае он отлично работает в Windows, но не в Linux.   -  person Ejaz Karim    schedule 04.12.2017
comment
Это ссылка, которая помогла решить мою проблему: github.com/facebook/create-react-app/blob/master/packages/   -  person jimbotron    schedule 10.07.2018


Ответы (52)


Глядя на комментарии к принятому ответу и общий характер этого вопроса («не работает»), я подумал, что это может быть хорошим местом для некоторых общих объяснений по затронутым здесь вопросам. Итак, этот ответ предназначен в качестве справочной информации / уточнения конкретного варианта использования OP. Пожалуйста, потерпите меня.

На стороне сервера или на стороне клиента

Первое, что нужно понять, это то, что теперь есть 2 места, где интерпретируется URL, тогда как раньше было только 1 место. Раньше, когда жизнь была простой, какой-то пользователь отправлял запрос http://example.com/about на сервер, который проверял часть пути URL-адреса, определял, что пользователь запрашивал страницу about, а затем отправлял эту страницу обратно.

С маршрутизацией на стороне клиента, которую предоставляет React-Router, все менее просто. Сначала у клиента еще нет загруженного JS-кода. Таким образом, самый первый запрос всегда будет к серверу. Затем будет возвращена страница, содержащая необходимые теги сценария для загрузки React и React Router и т. Д. Только после загрузки этих сценариев начинается фаза 2. На этапе 2, когда пользователь нажимает, например, ссылку навигации "О нас", URL-адрес изменяется только локально на http://example.com/about (что стало возможным благодаря разработчику History API), но запросы к серверу не выполняются. Вместо этого React Router делает свое дело на стороне клиента, определяет, какое представление React нужно отображать, и отображает его. Предполагая, что на вашей странице about не нужно выполнять какие-либо вызовы REST, это уже сделано. Вы перешли с главной страницы на раздел «О нас», но при этом не было запущено ни одного запроса сервера.

Таким образом, в основном, когда вы нажимаете ссылку, запускается некоторый Javascript, который манипулирует URL-адресом в адресной строке, не вызывая обновления страницы, что, в свою очередь, заставляет React Router выполнять переход страницы на клиенте -сайд.

Но теперь подумайте, что произойдет, если вы скопируете и вставите URL-адрес в адресную строку и отправите его другу по электронной почте. Ваш друг еще не загрузил ваш сайт. Другими словами, она все еще находится в фазе 1. На ее машине еще не запущен React Router. Таким образом, ее браузер сделает запрос сервера к http://example.com/about.

И здесь начинаются ваши проблемы. До сих пор вы могли обойтись простым размещением статического HTML-кода в корневом веб-сервере вашего сервера. Но это приведет к 404 ошибкам для всех остальных URL при запросе с сервера. Те же самые URL-адреса отлично работают на стороне клиента, потому что React Router выполняет маршрутизацию за вас, но они не работают на стороне сервера, если вы не дадите своему серверу понять их.

Комбинирование маршрутизации на стороне сервера и на стороне клиента

Если вы хотите, чтобы URL-адрес http://example.com/about работал как на стороне сервера, так и на стороне клиента, вам необходимо настроить маршруты для него как на стороне сервера, так и на стороне клиента. Имеет смысл, правда?

И здесь начинается ваш выбор. Решения варьируются от полного обхода проблемы с помощью всеобъемлющего маршрута, который возвращает загрузочный HTML-код, до полностью изоморфного подхода, когда и сервер, и клиент запускают один и тот же JS-код.

.

Полный обход проблемы: история хеширования

С помощью истории хеширования вместо История браузера, ваш URL-адрес для страницы с информацией будет выглядеть примерно так: http://example.com/#/about Часть после символа решетки (#) не отправляется на сервер. Таким образом, сервер видит только http://example.com/ и отправляет индексную страницу, как ожидалось. React-Router подберет #/about часть и покажет правильную страницу.

Минусы:

  • "уродливые" URL
  • При таком подходе рендеринг на стороне сервера невозможен. Что касается поисковой оптимизации (SEO), ваш веб-сайт состоит из одной страницы, на которой практически нет контента.

.

Поймать все

При таком подходе вы действительно используете историю браузера, но просто настраиваете на сервере всеохватывающую информацию, которая отправляет /* на index.html, что дает вам практически ту же ситуацию, что и с историей хеширования. Однако у вас есть чистые URL-адреса, и вы можете улучшить эту схему позже, не аннулируя все избранное пользователя.

Минусы:

  • Более сложный в настройке
  • Все еще нет хорошего SEO

.

Гибридный

В гибридном подходе вы расширяете всеобъемлющий сценарий, добавляя определенные сценарии для определенных маршрутов. Вы можете создать несколько простых сценариев PHP, чтобы возвращать самые важные страницы вашего сайта с включенным контентом, чтобы робот Googlebot мог, по крайней мере, видеть, что на вашей странице.

Минусы:

  • Еще сложнее настроить
  • Только хорошее SEO для тех маршрутов, которым вы уделяете особое внимание
  • Дублирование кода для рендеринга контента на сервере и клиенте

.

Изоморфный

Что, если мы используем Node JS в качестве нашего сервера, чтобы мы могли запускать один и тот же код JS на обоих концах? Теперь у нас есть все наши маршруты, определенные в одной конфигурации реактивного маршрутизатора, и нам не нужно дублировать наш код рендеринга. Это, так сказать, «Святой Грааль». Сервер отправляет ту же разметку, которую мы получили бы, если бы переход страницы произошел на клиенте. Это решение оптимально с точки зрения SEO.

Минусы:

  • Сервер должен (уметь) запускать JS. Я экспериментировал с Java i.c.w. Нашорн, но у меня это не работает. На практике это в основном означает, что вы должны использовать сервер на основе Node JS.
  • Множество сложных экологических проблем (использование window на стороне сервера и т. Д.)
  • Крутая кривая обучения

.

Что мне использовать?

Выберите тот, который вам сойдет с рук. Лично я считаю, что все достаточно просто настроить, так что это мой минимум. Эта настройка позволяет вам со временем улучшать ситуацию. Если вы уже используете Node JS в качестве серверной платформы, я бы определенно исследовал создание изоморфного приложения. Да, сначала это сложно, но как только вы освоитесь, это действительно очень элегантное решение проблемы.

По сути, для меня это был бы решающий фактор. Если мой сервер работает на Node JS, я бы стал изоморфным; в противном случае я бы выбрал решение Catch-all и просто расширил его (гибридное решение) по мере того, как время прогрессирует и этого требуют требования SEO.

Если вы хотите узнать больше об изоморфном (также называемом «универсальном») рендеринге с помощью React, есть несколько хороших руководств по этой теме:

Кроме того, для начала я рекомендую посмотреть несколько стартовых комплектов. Выберите тот, который соответствует вашему выбору для стека технологий (помните, React - это просто V в MVC, вам нужно больше материала для создания полноценного приложения). Начнем с того, что опубликовал сам Facebook:

Или выберите один из множества, предложенных сообществом. Теперь есть хороший сайт, который пытается их всех проиндексировать:

Я начал с этих:

В настоящее время я использую самодельную версию универсального рендеринга, вдохновленную двумя стартовыми наборами выше, но сейчас они устарели.

Удачи в поисках!

person Stijn de Witt    schedule 14.04.2016
comment
Отличный пост Stijn! Вы бы порекомендовали использовать стартовый комплект для приложения Isomorphic React? Если да, то не могли бы вы привести пример того, что вы бы предпочли? - person Chris; 29.04.2016
comment
@Chris Извините за задержку с ответом, я был в командировке. На самом деле я опробовал пару изоморфных стартовых наборов. Я добавлю немного информации об этом в свой пост. - person Stijn de Witt; 06.05.2016
comment
@Stijn - Это действительно прояснило для меня несколько вещей, спасибо. Не могли бы вы прояснить методику «всеобъемлющего»? На данный момент это кажется мне логичным шагом, но я не уверен, где найти более подробную информацию о том, как это сделать ... - person Paulos3000; 30.10.2016
comment
@ Paulos3000 Это зависит от того, какой сервер вы используете. По сути, вы определяете маршрут для /* и заставляете его отвечать вашей HTML-страницей. Сложность здесь в том, чтобы убедиться, что вы не перехватываете запросы на файлы .js и .css с этим маршрутом. - person Stijn de Witt; 30.10.2016
comment
@ Paulos3000 См. Здесь некоторые связанные вопросы: для Apache / php, для Express / js, для J2E / Java. - person Stijn de Witt; 30.10.2016
comment
Я бы использовал экспресс-сервер. Я видел его код, но не совсем уверен, как его интегрировать ... Как мне это сделать, например, с помощью webpack? - person Paulos3000; 30.10.2016
comment
@ Paulos3000 Express делает это очень просто. Просто убедитесь, что вы добавили что-нибудь к этому эффекту в качестве последнего обработчика: app.use('*', function(req, res, next) {res.send('<DOCTYPE html ....')}); - person Stijn de Witt; 01.11.2016
comment
... но, конечно, поскольку вы используете экспресс, вам действительно следует исследовать изоморфное / универсальное решение;) - person Stijn de Witt; 01.11.2016
comment
Интересно, что с тех пор, как я впервые создал этот ответ, сам Facebook представил стартовый комплект. Может, попробовать это? github.com/facebookincubator/create-react-app - person Stijn de Witt; 01.11.2016
comment
Большое вам спасибо - это прояснило для меня аспекты маршрутизации, которых не было в Google и чтении официальных документов React. Могу я предложить вам отправить его ребятам из React для включения в их документы? - person John McGrath; 17.12.2016
comment
@JohnMcGrath Спасибо и рад, что помог вам. Документы React Router, вероятно, были бы более подходящими. У них открытый исходный код, так что вы можете предложить это в качестве вклада ... Может быть, сначала покажите им этот пост и спросите, заинтересованы ли они? - person Stijn de Witt; 20.12.2016
comment
@Stijn de Witt Это отличное разъяснение и хороший ответ по этой теме. Однако каковы варианты, когда ваше приложение может обслуживаться в подкаталоге (например, с помощью iis). То есть: domain / appName / routeName или домен / имя приложения / подпапка / имя маршрута - person Sagiv b.g; 19.03.2017
comment
Привет, я пробую хеш-решение, но безуспешно. Получение createMemoryHistory is not a function ошибки. Не возражаете взглянуть? stackoverflow.com/questions/45002573/ - person Leon Gaban; 10.07.2017
comment
@LeonGaban Похоже, что с тех пор, как был написан этот ответ, React Router изменил свою реализацию. Теперь у них есть разные экземпляры Router для разных историй, и они выполняют настройку истории в фоновом режиме. Основные принципы остались прежними. - person Stijn de Witt; 17.07.2017
comment
@YarinDekel Спасибо! И да, возможно, вы правы насчет create-react-app, поскольку CRA не поддерживает SSR из коробки :( - person Stijn de Witt; 08.01.2019
comment
@Stijndewitt Я наткнулся на решение вроде упомянутого вами комплексного решения, которое могло бы устранить недостатки SEO. Однако это касается только кота. Может быть, стоит обновить свой ответ, включив его? - person ns533; 07.07.2019
comment
@ ns533 Не могли бы вы объяснить, как это устранило бы недостатки SEO? AFAICT, это похоже на правила перезаписи в Apache ... Это означает, что он все равно отправляет почти пустую страницу, на которой сканеры не смогут найти какой-либо контент. - person Stijn de Witt; 08.07.2019
comment
@StijndeWitt Если веб-сканер не отображает страницу с включенным JavaScript, я думаю, это не так. Я читал, что поисковые роботы Google видят всю страницу. Объединяя эту информацию с правилом if, которое перенаправляет www.mysite.com/blogpost/* на мой index.html (Google не мудрее), то не должен ли поисковый робот Google видеть каждый пост в блоге как уникальную страницу? - person ns533; 21.07.2019
comment
@ ns533 Да, я думаю, что Google сможет его проиндексировать, поскольку похоже, что они действительно используют javascript. Однако я не уверен, что, например, Bing и Yahoo делают ... - person Stijn de Witt; 31.07.2019
comment
@StijndeWitt Очень полезный пост, есть ли какой-либо ресурс, объясняющий этот подход Catch All, реализованный в .net? Я только что подумал, что шаблон веб-приложения .Net Core React, созданный Visual Studio, имеет именно такую ​​проблему. Попытка попасть в бэкэнд с URL-адресом работает впервые. Второй раз он больше никогда не переходит на серверную часть. Не могу найти способ решить эту проблему. - person Arthur Medeiros; 08.11.2019
comment
@StijndeWitt Действительно хорошее исчерпывающее объяснение. Я думаю, что универсальное решение не имеет большого значения и его легко настроить для таких серверных приложений, как Django. - person Mohammed Shareef C; 14.12.2019
comment
@ ns533 Я не думаю, что это решение ограничивается Tomcat. Nginx легко справится с этим. В любом случае это то же комплексное решение, но обрабатывается самим веб-сервером (или обратным прокси-сервером). - person Mohammed Shareef C; 14.12.2019
comment
Отличный ответ! Недавно я опубликовал статью, в которой есть несколько визуализаций того, что происходит во время маршрутизации. Надеюсь, это поможет valerii-udodov.com/2020 / 01/24 / Ура - person Val; 29.01.2020
comment
Одна вещь, на которую не удалось указать, заключалась в том, что если вы загрузите приложение, а затем вручную измените URL-адрес в браузере на URL-адрес, который поддерживает маршрутизатор, все приложение будет обновлено. У меня создалось впечатление, что браузер перенаправит это в приложение, но это не так. Браузер ничего не знает о React и просто делает то, что делает всегда, а именно загружает контент для URL-адреса из бэкэнда. - person AndroidDev; 10.04.2020
comment
Да, способ манипулировать URL-адресом, не заставляя его получать новую страницу с сервера, - это использовать History API. Вы можете открыть консоль разработчика и запустить там строку JS, если хотите протестировать клиентскую навигацию. - person Stijn de Witt; 12.04.2020
comment
@StijndeWitt Только что проголосовал за этот хорошо написанный ответ. :) Только одно: в подходе Catch-all, что это значит без необходимости аннулировать все избранное вашего пользователя? ???? - person Glenn Mohammad; 12.04.2020
comment
@GlennMohammad Представьте, что вы начинаете с подхода «История хеширования», и пользователи добавляют в избранное (закладку) https://example.com/#/about, если вы позже перейдете на рендеринг на стороне сервера, их закладки перестанут работать. Если вы начнете с Catch All и сделаете https://example.com/about return index.html, вы сможете позже реализовать рендеринг на стороне сервера, и пользовательские закладки по-прежнему будут работать. - person Stijn de Witt; 13.04.2020
comment
Я обнаружил забавную проблему с HashRouter: первый раз, когда я ввожу URL-адрес, он работает нормально, но если я снова набираю то же самое, приложение полностью перезагружается. Например, находясь в locahost:3000/, я набираю locahost:3000/test, которого не существует, тогда HashRouter не перезагружает страницу. Но если попытаться отправить тот же запрос еще раз locahost:3000/test приложение перезагружается ... Интересно, почему ... ???? - person Watchmaker; 20.04.2020
comment
ответ на этот вопрос очень хорошо объяснен, но я решил добавить import * as serviceWorker из ./serviceWorker; и serviceWorker.register () в App.js, и я могу обновить страницы без уродливых ссылок на URL: medium.com/@krishnarai1985/ - person EduardoUstarez; 17.09.2020
comment
@EduardoUstarez В общем случае ваше решение не работает. Просто отправьте ссылку другу по электронной почте, чтобы проверить ее. Сервис-воркеры - это клиентская вещь. Они работают только с клиентами, которые уже загружали страницу в прошлом и у которых установлен Service worker. Вам действительно нужно какое-то серверное решение, если вы хотите, чтобы ваши URL-адреса работали во всех случаях. - person Stijn de Witt; 28.12.2020
comment
Разве простое перенаправление ответов 404 и 403 на /index.html не решит проблему? - person tymik; 30.12.2020
comment
@tymik Я бы счел это грязным взломом. Я хочу, чтобы мой веб-сайт возвращал 404 для несуществующих URL. С таким решением все URL-адреса будут перенаправлены на index.html, но это не то, что я хочу, чтобы мой веб-сайт делал. Однако это может быть приемлемо для вас. - person Stijn de Witt; 03.01.2021
comment
Как начать с всеобъемлющего подхода? - person Yash Karanke; 04.01.2021
comment
@StijndeWitt, но вы должны обработать 404 в своем маршрутизаторе и вернуть все, что вы хотите, внутри своего приложения - это кажется довольно хорошим решением для одностраничных приложений. Таким образом, очень хорошо работает с CloudFront. - person tymik; 04.01.2021
comment
@YashKaranke Какой у вас сервер? Вы должны настроить его так, чтобы он возвращал index.html для всех URL-адресов, которые будет использовать ваше приложение. Но убедитесь, что он делает это только для HTML, а не для изображений, скриптов и т. Д. - person Stijn de Witt; 06.01.2021
comment
@StijndeWitt Apache, я добавил .htaccess файл в общую папку, и теперь он отлично работает - person Yash Karanke; 06.01.2021
comment
У меня есть решение для этого, недавно столкнулся с этой проблемой в проекте, вероятно, напишу ответ позже, когда у меня будет время - person Inzamam Malik; 10.07.2021
comment
нет необходимости использовать HashRouter - person Inzamam Malik; 10.07.2021

Все ответы здесь чрезвычайно полезны, что сработало для меня, так это настройка моего сервера Webpack для ожидания маршрутов.

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

HistoryApiFallback - это то, что решило эту проблему для меня. Теперь маршрутизация работает правильно, и я могу обновить страницу или ввести URL-адрес напрямую. Не нужно беспокоиться об обходных методах на вашем сервере узлов. Этот ответ, очевидно, работает только в том случае, если вы используете веб-пакет.

РЕДАКТИРОВАТЬ: см. Мой ответ здесь, чтобы подробнее узнать, почему это необходимо: https://stackoverflow.com/a/37622953/5217568 < / а>

person jmancherje    schedule 26.05.2016
comment
Обратите внимание, что команда Webpack не рекомендует использовать сервер разработки в производственной среде. - person Stijn de Witt; 13.06.2016
comment
Для общих целей разработки это лучшее решение. historyApiFallback достаточно. Что касается всех других опций, их также можно установить из интерфейса командной строки с помощью флага --history-api-fallback. - person Marco Lazzeri; 27.10.2016
comment
@Kunok Это не так. Это быстрое исправление для разработки, но вам все равно придется что-то придумать для производства. - person Stijn de Witt; 31.05.2017
comment
contentBase: ': /' потому что файлы вашего приложения могут быть доступны с URL-адреса - person Nezih; 21.02.2018
comment
У меня была эта проблема на сервере, а также локально. Это исправлено для локального. Исправлен .htaccess на сервере. - person Izabela Furdzik; 05.06.2021
comment
Работает для React 17. Спасибо - person prathameshk73; 26.06.2021

Вы можете изменить свой .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>

Я использую react: "^16.12.0" и react-router: "^5.1.2". Этот метод является универсальным и, вероятно, является самым простым способом начать работу.

person BrahimS    schedule 14.11.2016
comment
Это прекрасно работает! и самый простой, если вы не хотите реструктурировать свое приложение - person mhyassin; 13.02.2018
comment
Не забывайте RewriteEngine On в качестве первой строки - person Kai Qing; 01.11.2018
comment
Обратите внимание, что этот ответ относится к конфигурации на сервере Apache. Это не часть приложения React. - person Colton Hicks; 17.07.2019
comment
Я не понял ответов выше. Ни один из наставников не сказал, что мои ссылки вообще не будут работать вживую. Однако этот простой файл htaccess работал. Спасибо - person Thomas Williams; 26.03.2020
comment
Это также работает для статического экспорта next.js. Поскольку tomcat не похож на node, нам нужна эта дополнительная конфигурация для статического экспорта next.js. - person giri-jeedigunta; 04.04.2020
comment
Это прекрасно работает, что, вероятно, не случайно. 80% моих глубоких URL-адресов теперь могут быть обновлены, что является явным улучшением. - person Chris G; 29.05.2020
comment
Может кто-нибудь мне помочь? Куда поставить этот htaccess? Вам нужно запустить сборку npm после добавления файла? - person Muteshi; 05.09.2020
comment
Я npm run build, а затем добавил это в .htacess в папку сборки и загрузил на cPanel, но все еще не работает - person Tayyab Ferozi; 10.12.2020
comment
@TayyabFerozi Вы должны убедиться, что путь после RewriteBase и после последнего RewriteRule соответствует папке, в которой находится приложение (если это подпапка) - person Jason Ellis; 22.12.2020
comment
У меня была эта проблема на сервере, а также локально. Это исправлено для сервера. Конфигурация devServer исправила это локально. - person Izabela Furdzik; 05.06.2021

Для пользователей React Router V4:

Если вы попытаетесь решить эту проблему с помощью техники Hash History, упомянутой в других ответах, обратите внимание, что

<Router history={hashHistory} >

не работает в V4, используйте вместо этого HashRouter:

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

<HashRouter>
  <App/>
</HashRouter>

Ссылка: HashRouter

person user2875289    schedule 18.04.2017
comment
Не могли бы вы подробно рассказать, почему HashRouter решает эту проблему? Ссылка, которую вы предоставили, мне не объясняет. Кроме того, есть ли способ скрыть хеш в пути? Я использовал BrowserRouter, но столкнулся с этой проблемой 404 .. - person Ian Smith; 07.06.2020
comment
Я использовал маршрутизатор браузера, и он вызывал ошибку 404 при обновлении, но затем я заменил маршрутизатор браузера на хэш-маршрутизатор, и он не работает нормально. Спасибо - person newbie; 31.07.2020

Я только что использовал приложение create-react-app для создания веб-сайта, и у меня возникла та же проблема, что и здесь. Я использую BrowserRouting из пакета react-router-dom. Я работаю на сервере Nginx, и для меня это решило добавление следующего в /etc/nginx/yourconfig.conf

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

Что соответствует добавлению следующего в .htaccess, если вы используете Appache

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

Это также кажется решением, предложенным самим Facebook, и его можно найти здесь

person Aidin    schedule 04.09.2017
comment
Ух ты, такое простое решение для nginx; работает как шарм, как новый пользователь nginx. Просто скопируйте-вставьте и готово. +1 за ссылку на официальную документацию fb. Путь к работе. - person user3773048; 13.01.2019
comment
Для справки: я использую экземпляр AWS с nginx и приложением Angular. Это работает. - person Diego Sarmiento; 03.06.2019
comment
ты спасаешь меня. Я пытался решить свою проблему со вчерашнего дня, я устал от нескольких решений, но я потерпел неудачу. наконец, вы помогли мне решить эту проблему с маршрутизатором. ах, спасибо большое, брат - person Sharifur Robin; 22.09.2019
comment
Нужно ли что-то другое для реакции: ^ 16.8.6, реактивного маршрутизатора: ^ 5.0.1? Я пробовал эти решения (как nginx, так и apache), и они не работают. - person Mark A. Tagliaferro; 21.10.2019
comment
Поскольку Facebook не менял свою документацию по этому поводу, я могу только предположить, что процедура такая же. Хотя я давно не пробовал. - person Aidin; 21.10.2019
comment
Работаем с этим неделями, и это единственное решение, которое работает. Спасибо - person abby; 29.05.2020
comment
Привет, не могли бы вы рассказать мне, как это будет работать, если папка React является псевдонимом, а не root? - person krishna lodha; 25.05.2021

В свой index.html head добавьте следующее:

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

Затем при работе с сервером webpack dev используйте эту команду.

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

--history-api-fallback - важная часть

person Efe Ariaroo    schedule 01.04.2018
comment
Это отлично сработало! Есть ссылки, чтобы узнать больше о том, как вы получили / нашли это решение? - person justDan; 26.06.2018
comment
Извини брат. Нашел его испытанным методом проб и ошибок. - person Efe Ariaroo; 30.06.2018
comment
Стоит отметить, что если вы используете базовый href, отличный от /, HashRouter не будет работать (если вы используете хэш-маршрутизацию). - person scrowler; 17.01.2019
comment
Тег ‹base href = /› сделал это за меня. Спасибо за это. Сервер разработчика Webpack продолжал пытаться получить пакет по пути / ‹bundle› и терпел неудачу. - person Malisbad; 26.03.2019
comment
Я использую режим React.js + Webpack. Я добавил параметр --history-api-fallback в файл package.json. Тогда обновление страницы работает правильно. Каждый раз, когда я меняю код, веб-страница обновляется автоматически. `` скрипты: {start: rimraf build && cross-env NODE_ENV = 'development' webpack --mode development && cross-env NODE_ENV = development webpack-dev-server --history-api-fallback, ...} ' ` - person NinjaDev; 13.08.2020

Маршрутизатор может вызываться двумя разными способами, в зависимости от того, происходит ли навигация на клиенте или на сервере. Вы настроили его для работы на стороне клиента. Ключевым параметром является второй параметр после метода запуска, местоположение .

Когда вы используете компонент React Router Link, он блокирует навигацию браузера и вызывает transitionTo для выполнения навигации на стороне клиента. Вы используете HistoryLocation, поэтому он использует API истории HTML5, чтобы создать иллюзию навигации, имитируя новый URL-адрес в адресной строке. Если вы используете старые браузеры, это не сработает. Вам нужно будет использовать компонент HashLocation.

Когда вы нажимаете «Обновить», вы обойдете весь код React и React Router. Сервер получает запрос на /joblist и должен что-то вернуть. На сервере вам необходимо передать запрошенный путь методу run, чтобы он отображал правильное представление. Вы можете использовать ту же карту маршрутов, но вам, вероятно, понадобится другой вызов Router.run. Как указывает Чарльз, вы можете использовать перезапись URL, чтобы справиться с этим. Другой вариант - использовать сервер node.js для обработки всех запросов и передать значение пути в качестве аргумента местоположения.

В экспресс, например, это может выглядеть так:

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

Обратите внимание, что путь запроса передается run. Для этого вам понадобится механизм просмотра на стороне сервера, которому вы можете передавать отрисованный HTML. Есть ряд других соображений, касающихся использования renderToString и запуска React на сервере. Как только страница отображается на сервере, когда ваше приложение загружается в клиенте, оно будет отображаться снова, обновляя отображаемый HTML-код на стороне сервера по мере необходимости.

person Todd    schedule 21.01.2015
comment
извините Извините, не могли бы вы объяснить, пожалуйста, следующее утверждение, когда вы нажимаете «Обновить», вы обойдете весь код React и React Router? Почему это происходит? - person VB_; 08.09.2015
comment
Маршрутизатор React обычно используется для обработки различных «путей» только в браузере. Это можно сделать двумя типичными способами: хеш-путь старого стиля и новый API истории. При обновлении браузера будет сделан запрос к серверу, который будет обходить ваш код маршрутизатора реакции на стороне клиента. Вам нужно будет обработать путь на сервере (но только если вы используете API истории). Вы можете использовать для этого реактивный маршрутизатор, но вам нужно будет сделать что-то похожее на то, что я описал выше. - person Todd; 09.09.2015
comment
понятно. Но как быть, если сервер не на языке JS (допустим, Java)? - person VB_; 09.09.2015
comment
В этом случае все становится сложнее. Перспективы изоморфных приложений лучше всего реализовать с помощью JS на клиенте и сервере. Если вы не можете запускать JS в своей среде Java, у вас действительно не будет изоморфизма, и вы не сможете использовать реагирующий маршрутизатор. Есть некоторые серверные решения, такие как ReactJS.NET, которые могут делать подобные вещи. Однако использовать Node.js проще. - person Todd; 11.09.2015
comment
каков первый параметр в этом ответе? Потому что, когда вы включаете что-то вроде ‹Route name = root path = / handler = {App} /›, вы получаете ошибку SyntaxError: Unexpected token ‹ - person Code Uniquely; 15.10.2015
comment
извините ... вы имеете в виду, что вам требуется экспресс-сервер для рендеринга маршрута, который не является корневым? Сначала меня поразило то, что определение изоморфизма не включало выборку данных в свою концепцию (все очень сложно, если вы хотите отображать представление со стороны сервера данных, хотя это было бы очевидной потребностью SEO - и изоморфизм утверждает это). Теперь я как WTF реагирую, серьезно… Поправьте меня, если я ошибаюсь, требуется ли ember / angular / backbone сервер для рендеринга маршрута? Я действительно не понимаю этого раздутого требования использовать маршруты - person Ben; 17.10.2015
comment
@Ben Поправьте меня, если я ошибаюсь, требуется ли для ember / angular / backbone сервер для рендеринга маршрута? Да, на самом деле они есть, когда вы используете местоположение в истории («настоящие URL-адреса»). Все фреймворки Javascript это делают. Помните, что когда вы запрашиваете URL-адрес, вы сначала попадаете на сервер. Что происходит, так это то, что OP неправильно маршрутизирует на стороне сервера. Ему следует либо просто использовать хэш-адрес, либо настроить сервер так, чтобы он всегда обслуживал HTML по всем возможным маршрутам. - person Stijn de Witt; 17.11.2015
comment
Означает ли это, что обновление в реактивном маршрутизаторе не работает, если мое приложение реакции не изоморфно? - person Matt; 07.12.2015
comment
Чтобы обновление заработало, вам необходимо вызвать маршрутизатор из клиентского кода (среда React по умолчанию) и из серверного кода (Node.js). Если вы можете это сделать, ваше приложение изоморфно. Обратите внимание, что код в этом ответе не отражает изменений в новой версии React Router 1.0 (на данный момент). - person Todd; 08.12.2015
comment
@Matt Если ваше приложение для реагирования не изоморфно (или, может быть, вы даже не используете JS на стороне сервера, но, скажем, PHP), лучше всего иметь сценарий на стороне сервера, который возвращает одну и ту же страницу для всех возможные маршруты. Клиенту будет отправлен только некоторый общий начальный HTML-код. Оказавшись на клиенте, React-Router просматривает URL-адрес, и все будет работать, как ожидалось. Но обратная сторона связана с SEO. Google будет видеть только этот загрузочный HTML и не будет индексировать ваш сайт. - person Stijn de Witt; 14.04.2016

Если вы используете приложение Create React:

Тем не менее, есть отличное решение этой проблемы с решениями для многих основных хостинговых платформ, которые вы можете найти ЗДЕСЬ на странице создания приложения React. Например, я использую React Router v4 и Netlify для своего внешнего кода. Все, что потребовалось, - это добавить 1 файл в мою общую папку ("_redirects") и одну строку кода в этом файле:

/*  /index.html  200

Теперь мой веб-сайт правильно отображает такие пути, как mysite.com/pricing, при вводе в браузер или когда кто-то нажимает кнопку «Обновить».

person Colton Hicks    schedule 09.06.2017
comment
если вы используете HTTP-сервер Apache, тогда .htaccess не работает, проверьте версию apache, потому что в версии 2.3.9 и новее AllowOverride <по умолчанию / b> равно Нет, попробуйте изменить AllowOverride на Все. проверьте этот ответ - person Muhammad Adam C; 13.04.2021

Если вы размещаете приложение React через AWS Static S3 Hosting и CloudFront

Эта проблема возникла из-за того, что CloudFront ответил сообщением 403 Access Denied, потому что ожидалось, что / some / other / path будет существовать в моей папке S3, но этот путь существует только внутри маршрутизации React с помощью response-router.

Решением было установить правило распределения страниц ошибок. Зайдите в настройки CloudFront и выберите свою раздачу. Затем перейдите на вкладку «Страницы ошибок». Нажмите «Создать настраиваемый ответ на ошибку» и добавьте запись для 403, поскольку это код состояния ошибки, который мы получаем. Установите Путь к странице ответа на /index.html, а код состояния на 200. Конечный результат меня поражает своей простотой. Страница индекса обслуживается, но URL-адрес сохраняется в браузере, поэтому после загрузки реагирующего приложения оно определяет путь URL-адреса и переходит к желаемому маршруту.

Правило страницы ошибок 403

person th3morg    schedule 23.11.2017
comment
Это именно то, что мне нужно. Спасибо. - person Jonathan; 19.09.2019
comment
Итак .. все ваши URL-адреса работают, но возвращают код статуса 403? Это не так. Ожидаемые коды состояния должны быть в диапазоне 2xx. - person Stijn de Witt; 21.10.2019
comment
@StijndeWitt Я не уверен, что вы правильно поняли. CloudFront справится со всем - клиент не увидит никаких кодов состояния 403. Перенаправление происходит на стороне сервера, отображается страница индекса, сохраняется URL-адрес и в результате предоставляется правильный маршрут. - person th3morg; 22.10.2019
comment
@ th3morg Ах, да, теперь понятно. Я пропустил, что он также позволяет вам заполнить код состояния ответа как 200. Таким образом, в основном вы сопоставляете статус 403 со статусом 200 ... Выглядит нормально ... за исключением того, что, возможно, вы получите 403 в результате по какой-то другой причине из-за этого вы не сможете его увидеть. - person Stijn de Witt; 23.10.2019
comment
@StijndeWitt Это именно 403 от CloudFront, поэтому, если бы вы сказали, что выполняли вызов API, который привел к асинхронному ответу 403 с вашего сайта, это было бы нормально. Я не могу представить себе сценарий, в котором вы захотели бы раскрыть поведение 403 из самого CloudFront, хотя, возможно, он есть. Это решение должно работать в более чем 99% случаев использования. - person th3morg; 23.10.2019
comment
спасибо за это @ th3morg. Эта настройка также работает для многоуровневых путей? Он отлично работает для меня, если какой-либо путь на корневом уровне, например домен / регистрация, домен / логин, домен / ‹documentId›, но он не работает для многоуровневых путей, таких как domain / document / ‹documentId›. - person Pargles; 03.02.2020
comment
О ты прекрасное существо! Требовалось установить его для ответа 404, и он работал как шарм! - person Nnanyielugo; 06.07.2020

Это может решить вашу проблему

Я также столкнулся с той же проблемой в приложении ReactJS в производственном режиме. Вот 2 решения проблемы.

1. Измените историю маршрутизации на hashHistory вместо browserHistory вместо

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

Теперь создайте приложение с помощью команды

sudo npm run build

Затем поместите папку сборки в папку var / www /. Теперь приложение работает нормально с добавлением тега # в каждый URL. нравиться

локальный / # / домашний локальный / # / aboutus

Решение 2. Без тега # с использованием browserHistory,

Установите в маршрутизаторе свой history = {browserHistory}. Теперь создайте его с помощью sudo npm run build.

Вам нужно создать файл conf, чтобы решить страницу 404 not found, файл conf должен быть таким.

откройте свой терминал, введите следующие команды

cd / etc / apache2 / sites-available ls nano sample.conf Добавьте в него приведенное ниже содержимое.

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

Теперь вам нужно включить файл sample.conf с помощью следующей команды

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

затем он попросит вас перезагрузить сервер apache, используя sudo service apache2 reload или перезапустить

затем откройте папку localhost / build и добавьте файл .htaccess с приведенным ниже содержимым.

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

Теперь приложение работает нормально.

Примечание: измените IP-адрес 0.0.0.0 на свой локальный IP-адрес.

Если есть сомнения по этому поводу, не стесняйтесь поднять комментарий.

Я надеюсь, что это поможет другим.

person Venkatesh Somu    schedule 07.02.2017
comment
Будет ли первое решение работать для "react-router-dom": "^5.1.2"?, Я использую <BrowserRouter> - person 151291; 13.12.2019
comment
.htaccess исправил это для меня. - person beltrone; 03.02.2021
comment
где я получу browserHistory в решении 2. - person Sushil; 06.02.2021
comment
добавление только файла .htaccess в папку сборки исправлено для меня, спасибо, человек - person coderLogs; 19.05.2021

Если вы размещаете свое приложение для реагирования на IIS, просто добавьте файл web.config, содержащий:

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

Это укажет серверу IIS вернуть клиенту главную страницу вместо ошибки 404 и не использовать историю хеширования.

person Chtiwi Malek    schedule 18.10.2017

У Webpack Dev Server есть возможность включить это. Откройте package.json и добавьте --history-api-fallback. Эти решения сработали для меня.

response-router- руководство

person sree    schedule 09.09.2016
comment
Это нормально с webpack-dev-server, но как мне исправить это для производственной сборки? - person Hussain; 15.08.2018

Рабочий стек: React, React Router v4, BrowswerRouter, Express, Nginx

1) User BrowserRouter для красивых URL

// app.js

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

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

2) Добавьте index.html ко всем неизвестным запросам с помощью /*

// 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) связать веб-пакет с webpack -p

4) запустите nodemon server.js или node server.js

РЕДАКТИРОВАТЬ: вы можете позволить nginx обрабатывать это в блоке сервера и игнорировать шаг 2:

location / {
    try_files $uri /index.html;
}
person Isaac Pak    schedule 09.08.2017
comment
получение пути неопределенного - person Goutham; 10.08.2017
comment
@Goutham Вверху файла server.js добавьте import path from 'path или const path = require('path') - person Isaac Pak; 10.08.2017
comment
шаг 2 (поймать все с /*) только что спас мне день. Спасибо! :) - person Atlas7; 22.11.2017
comment
Это работает, для людей, использующих redux и связанных с подключенным маршрутизатором, см. Этот пример: github.com/supasate/connected-react-router/tree/master/examples/ - person cjjenkinson; 16.04.2018

Добавьте это в webpack.config.js:

devServer: {
    historyApiFallback: true
}
person suraj    schedule 11.09.2017
comment
Это отлично подходит для разработчиков, но не помогает в производственных сборках. - person KFunk; 05.05.2020

Попробуйте добавить файл «.htaccess» в общую папку с помощью приведенного ниже кода.

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

RewriteRule ^ /index.html [L]  
person Kiran Joshi    schedule 29.06.2018
comment
Спасибо, у меня это сработало в Fedora 28 с apache. Ни одно из вышеперечисленных правил перезаписи, ни правила на странице CRA не помогли мне. Я добавил их в настройку виртуального хоста, а не в отдельный файл .htaccess. - person boerre; 25.11.2019

Если у вас есть резервный вариант для вашего index.html, убедитесь, что в вашем файле index.html есть следующее:

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

Это может отличаться от проекта к проекту.

person Matt Goo    schedule 03.05.2016
comment
Добавьте это в свой html head: ‹base href = /› - person Efe Ariaroo; 02.04.2018

Если вы используете firebase, все, что вам нужно сделать, это убедиться, что у вас есть свойство rewrites в вашем файле firebase.json в корне вашего приложения (в разделе хостинга).

Например:

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

Надеюсь, это избавит кого-то еще от кучи разочарований и зря потраченного времени.

Удачного кодирования ...

Дополнительная литература по теме:

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

Firebase CLI: настроить как одностраничное приложение (перепишите все URL-адреса в /index.html)

person Joshua Dyck    schedule 24.07.2018
comment
Ты легенда - person Perniferous; 29.03.2019

Для тех, кто использует IIS 10, вы должны сделать это правильно. Убедитесь, что вы используете с этим browserHistory. Что касается справки, я дам код для маршрутизации, но не это имеет значение, важен следующий шаг после кода компонента ниже:

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

Поскольку проблема в том, что IIS получает запрос от клиентских браузеров, он интерпретирует URL-адрес, как если бы он запрашивал страницу, а затем возвращает страницу 404, поскольку доступной страницы нет. Сделайте следующее:

  1. Откройте IIS
  2. Разверните Сервер, затем откройте папку Сайтов.
  3. Щелкните веб-сайт / приложение
  4. Перейти на страницы ошибок
  5. Откройте в списке пункт состояния ошибки 404
  6. Вместо параметра «Вставить содержимое из статического файла в ответ об ошибке» измените его на «Выполнить URL-адрес на этом сайте» и добавьте к URL-адресу значение косой черты «/».

И теперь будет нормально работать.

введите здесь описание изображения  введите описание изображения здесь

Я надеюсь, что это помогает. :-)

person Martin Lloyd Jose    schedule 29.05.2018
comment
лучшее решение после 3-4 часов поисков. большое спасибо :) - person KMR; 17.09.2020
comment
да благословит тебя Бог, мужик - person ArtemiZ Studio; 01.06.2021

Я нашел решение для своего SPA с реагирующим маршрутизатором (Apache). Просто добавьте .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>

источник: https://gist.github.com/alexsasharegan/173878f9d67055bfef63449fa71360

person Sasha Ignashevich    schedule 20.01.2019

Я еще не использую рендеринг на стороне сервера, но я столкнулся с той же проблемой, что и OP, где Link, казалось, работал нормально большую часть времени, но не работал, когда у меня был параметр. Я задокументирую свое решение здесь, чтобы посмотреть, поможет ли оно кому-нибудь.

Мой основной jsx содержит это:

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

Это отлично работает для первой совпадающей ссылки, но когда: id изменяется в <Link> выражениях, вложенных на страницу сведений о модели, URL-адрес изменяется в строке браузера, но содержимое страницы изначально не изменилось, чтобы отразить связанную модель.

Проблема заключалась в том, что я использовал props.params.id, чтобы установить модель в componentDidMount. Компонент монтируется только один раз, поэтому это означает, что первая модель - это та, которая остается на странице, а последующие ссылки изменяют свойства, но оставляют страницу без изменений.

Установка модели в состояние компонента как в componentDidMount, так и в componentWillReceiveProps (где она основана на следующих свойствах) решает проблему, и содержимое страницы изменяется, чтобы отразить желаемую модель.

person Paul Whipp    schedule 12.09.2016
comment
Возможно, лучше использовать конструктор компонента (который также имеет доступ к props) i.s.o. componentDidMount, если вы когда-нибудь захотите попробовать рендеринг на стороне сервера. Потому что componentDidMount вызывается только в браузере. Его цель - делать что-то с DOM, например, прикреплять слушателей событий к body и т. Д., Что вы не можете делать в render. - person Stijn de Witt; 20.12.2016

Эта тема немного устарела и решена, но я хотел бы предложить вам простое, понятное и лучшее решение. Это работает, если вы используете веб-сервер.

Каждый веб-сервер имеет возможность перенаправить пользователя на страницу с ошибкой в ​​случае http 404. Чтобы решить эту проблему, вам необходимо перенаправить пользователя на страницу индекса.

Если вы используете базовый сервер Java (tomcat или любой сервер приложений Java), решение может быть следующим:

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>

Пример:

  • ПОЛУЧИТЬ http://example.com/about
  • Веб-сервер выдает http 404, потому что эта страница не существует на стороне сервера
  • конфигурация страницы ошибки сообщает серверу, который отправляет страницу index.jsp обратно пользователю
  • тогда JS выполнит остальную работу на стороне клиента, поскольку URL-адрес на стороне клиента по-прежнему http://example.com/about.

Вот и все, магии больше не нужно :)

person zappee    schedule 15.01.2017
comment
Это было потрясающе! Я использую сервер Wildfly 10.1 и внес это обновление в свой файл web.xml, за исключением того, что у меня было указано местоположение только «/». Это произошло потому, что в моем коде реакции я использовал историю браузера следующим образом: const browserHistory = useRouterHistory(createHistory)({ basename: '/<appname>' }); - person Chuck L; 02.06.2017
comment
Вы уверены, что это не повлияет на SEO? Вы присваиваете статус 404 реально существующим страницам. Пользователь может никогда этого не понять, но боты уделяют много внимания, на самом деле, настолько, что они не будут очищать вашу страницу. - person subharb; 15.12.2017

Если вы используете Express или какой-либо другой фреймворк в бэкэнде, вы можете добавить аналогичную конфигурацию, как показано ниже, и проверить общедоступный путь Webpack в конфигурации, он должен работать нормально даже при перезагрузке, если вы используете BrowserRouter.

expressApp.get('/*', (request, response) => {
    response.sendFile(path.join(__dirname, '../public/index.html'));
});
person neeraj-dixit27    schedule 09.03.2018
comment
это самое простое решение. обратите внимание, этот маршрут должен идти после любых других маршрутов, так как это уловка всех - person dcsan; 14.02.2020

Исправление ошибки «не удается получить / URL» при обновлении или при прямом вызове URL.

Настройте свой webpack.config.js так, чтобы данная ссылка имела такие маршруты.

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

Вы можете попробовать все это прочитать, хотя это не мое:

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

Исправление маршрутизации приложения Теперь вот как наконец исправить маршрутизацию. Чтобы указать Apache перенаправить запросы на index.html, где находится наше приложение, мы должны изменить файл .htaccess. Если такого файла в папке вашего приложения еще нет, просто создайте его.

Затем убедитесь, что вы вставили эти 4 строки, которые волшебным образом заставят вашу маршрутизацию работать.

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

После того, как мы поместим этот файл .htaccess в тот же каталог, что и index.html, Apache будет перенаправлять каждый новый запрос прямо в ваше приложение.

Бонус: развертывание приложения React в подкаталоге

Если вы развертываете свое приложение в подкаталоге, чтобы оно было доступно, например через https://myapp.com/the-app, вы скоро заметите, что есть еще один проблема. Каждый щелчок по новому маршруту преобразует URL-адрес во что-то вроде https://myapp.com/route-abc - который снова сломается после перезагрузки. Но для этого есть простое решение:

BrowserRouter имеет свойство basename, в котором вы можете указать путь к подкаталогу:

From now on, each Route like /contacts will result in an URL like http://myapp.com/the-app/contacts.

person Rishabh Jain    schedule 14.10.2019
comment
Это очень простое решение для тех, кто хочет запускать CRA из другого каталога. Я использую react-router-dom, поэтому мне пришлось включить basename в <BrowserRouter />. Но это простое решение сэкономит вам много времени. Спасибо за этот вклад! - person Josh Cronkhite; 17.09.2020
comment
Спасибо. Ваше решение сэкономит мне время. :) - person Adnan Ahmad; 18.11.2020
comment
Рад, что смог помочь .. :) - person Rishabh Jain; 09.12.2020

Использование HashRouter также работало для меня с Redux, просто замените:

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

to:

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();
person Alireza    schedule 24.03.2020

Если вы используете команду create-response-app,

чтобы сгенерировать приложение для реагирования, в package.json должно быть одно изменение для правильной работы производственной сборки React SPA в браузере. Откройте package.json и добавьте к нему следующий сегмент кода,

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

Здесь самая важная часть - это --history-api-fallback, чтобы включить обратный вызов API истории.

Иногда вы получаете ошибку 404, если используете Spring или любой другой серверный API. Таким образом, в такой ситуации вам необходимо иметь контроллер в серверной части для пересылки любого запроса (по вашему желанию) в файл index.html для обработки с помощью response-router. Ниже показан пример контроллера, написанного с использованием spring.

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

например, если мы возьмем конечную точку REST внутреннего API как abc (http: // localhost: 8080 / abc / **), любой запрос, поступающий в эту конечную точку, будет перенаправлен на реагирующее приложение (файл index.html) и реагировать- router обработает это послесловие.

person Malinda    schedule 30.01.2020
comment
Вы также можете добавить несколько сопоставлений, например: @RequestMapping ({/ myurl1 / **, / myurl2 / **}) - person Craigo; 17.12.2020

В случае, если кто-то здесь ищет решение по React JS SPA с Laravel. Принятый ответ - лучшее объяснение того, почему возникают такие проблемы. Как уже объяснялось, вам необходимо настроить как клиентскую, так и серверную стороны. В свой шаблон лезвия включите связанный файл js, обязательно используйте URL facade, как это

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

В своих маршрутах обязательно добавьте это в основную конечную точку, где находится шаблон лезвия. Например,

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

Вышеупомянутое является основной конечной точкой для шаблона лезвия. Теперь добавьте необязательный маршрут,

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

Возникающая проблема заключается в том, что сначала загружается шаблон блейд-сервера, а затем - реагирующий маршрутизатор. Итак, когда вы загружаете '/setting-alerts', он загружает HTML и js. Но когда вы загружаете '/setting-alerts/about', он сначала загружается на стороне сервера. Поскольку на стороне сервера в этом месте ничего нет, возвращается значение «Не найдено». Когда у вас есть этот дополнительный маршрутизатор, он загружает ту же страницу, и также загружается реагирующий маршрутизатор, а затем загрузчик реагирования решает, какой компонент отображать. Надеюсь это поможет.

person Koushik Das    schedule 14.11.2017
comment
Можно ли загрузить один точный URI на сервер, а затем сервер сделает перенаправление на React? Например, когда я загружаю /user/{userID}, мне просто нужно вернуть универсальное /user HTML-представление, ввести идентификатор и вызвать его с помощью AJAX или axios. Возможно ли это? они оптимизированы для SEO? - person Ryuujo; 22.02.2019
comment
Я использую этот код для своего SPA с серверной частью Laravel: Route::any('{any?}', 'MyController@index'); Он соответствует любому маршруту и ​​передает его в SPA. - person Felix Geenen; 08.09.2020

Поскольку я использую .Net Core MVC, мне помогло что-то вроде этого:

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

В основном на стороне MVC все несоответствующие маршруты попадут в Home/Index, как указано в startup.cs. Внутри Index можно получить исходный URL-адрес запроса и передать его там, где это необходимо.

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" });
        });
person Elnoor    schedule 11.03.2019
comment
Если веб-API отделен от приложения, как вы с этим справитесь? - person Dayán Ruiz; 01.05.2019
comment
@ dayanrr91, если в вашем проекте есть веб-API, маршрутизация на стороне сервера вам в любом случае не понадобится. И ваш реактивный маршрутизатор, я считаю, должен читать URL-адрес и выполнять соответствующую маршрутизацию. Ничто не должно блокировать это - person Elnoor; 01.05.2019
comment
Ваш комментарий очень признателен, но тогда у меня есть вопрос, я только что добавил HashRouter, но теперь, когда я ввожу любой URL-адрес вручную, он будет перенаправлен на мой домашний компонент вместо перенаправления на мой домашний, а затем на компонент, который я пытался входя, есть ли какое-нибудь обходное решение для этого? - person Dayán Ruiz; 01.05.2019
comment
@ dayanrr91 понятия не имею, никогда не пробовал hashrouter, но я думаю, что это должно быть связано с вашим кодом. Принцип работы hashrouter должен быть похож на browserrouter. Также я только что протестировал здесь, в этой песочнице, он отлично работает codesandbox.io/s/25okp1mny, протестируйте url 25okp1mny.codesandbox.io/#/roster/5 - person Elnoor; 01.05.2019

Если вы размещаете в IIS; Добавление этого в мой webconfig решило мою проблему

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

Вы можете сделать аналогичную конфигурацию для любого другого сервера.

person Barny    schedule 26.04.2017

Для тех из вас, кто находится здесь, потому что вы пытаетесь обслуживать приложение для реагирования из виртуального каталога IIS (а не из корня веб-сайта), это может быть для вас.

При настройке ваших перенаправлений '/' не будет работать сам по себе, мне также нужно было указать имя виртуального каталога. Вот как выглядела моя веб-конфигурация:

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

В дополнение к файлу web.config самому реагирующему приложению потребуются некоторые изменения:

в package.json вам нужно добавить запись «домашняя страница»:

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

Я добавил базовое имя к объекту истории моего браузера, которое я передаю маршрутизатору, чтобы получить доступ к истории:

import  {createBrowserHistory } from 'history';

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

Я также добавил это свойство на моем маршрутизаторе React в App.js:

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

Наконец, в index.html я добавил следующую вкладку над тегом title.

  <base href="%PUBLIC_URL%/">

возможно, некоторые шаги требуют примечания, но, похоже, это сработало за меня. Я не знаю, как настроить его для запуска в корне сайта или в виртуальном каталоге без перекомпиляции, хотя, насколько мне известно, домашнюю страницу в package.json нельзя поменять местами после сборки.

person WraithNath    schedule 19.07.2020
comment
Меня спасли две последние строчки кода в вашем посте. Спасибо! basename в <Router /> и <base /> в index.html. - person Craig Howell; 28.04.2021
comment
@CraigHowell - Рад, что помог! Я тоже вернулся к этому посту, чтобы напомнить себе! - person WraithNath; 30.04.2021

Действительно потрясающие ответы уже !! Но если вы размещаете с помощью nginx и нуждаетесь в быстром исправлении ... добавьте следующую строку в конфигурацию nginx внутри блока местоположения

location / {
  try_files $uri /index.html;
}
person BeK    schedule 18.03.2021

Добавление дополнительной информации к ответу Джошуа Дейка.

Если вы используете Firebase и хотите использовать как корневой маршрут, так и маршрут подкаталога, вам необходимо добавить следующий код в свой firebase.json:

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

Пример:

Вы создаете сайт для клиента. Вы хотите, чтобы владелец веб-сайта добавил информацию в https://your.domain.com/management. в то время как пользователи веб-сайта будут переходить на https://your.domain.com.

В этом случае ваш firebase.json файл будет выглядеть так:

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

Я использую WebPack, у меня была такая же проблема Решение => В вашем файле server.js

const express = require('express');
const app = express();

app.use(express.static(path.resolve(__dirname, '../dist')));
  app.get('*', function (req, res) {
    res.sendFile(path.resolve(__dirname, '../dist/index.html'));
    // res.end();
  });

Почему не Не отображается ли мое приложение после обновления?

person Vishal Singh    schedule 19.02.2019
comment
Это сделало это для меня! Изначально у меня был res.sendFile (path.JOIN (publicPath, index.html)); Я изменил соединение на разрешенное, как в примере выше, на: res.sendFile (path.resolve (./ dist, index.html)); Я также играл с __dirname, но не мог понять его или заставить его работать, поэтому я вручную скопировал ./dist, потому что это то, откуда мой index.html обслуживается. Я тоже так заявлял ранее: app.use (express.static (./ dist)); - person logixplayer; 10.05.2020

Мы использовали экспресс-подход к обработке ошибки 404

// path to the static react build directory    
const frontend = path.join(__dirname, 'react-app/build');

// map the requests to the static react build directory
app.use('/', express.static(frontend));

// all the unknown requests are redirected to the react SPA
app.use(function (req, res, next) {
    res.sendFile(path.join(frontend, 'index.html'));
});

Работает как шарм. Живая демонстрация - на нашем сайте

person Zameer Ansari    schedule 22.09.2019
comment
это сработало для меня, спасибо за ваш ответ! - person Apostolos; 13.05.2021

Я решил эту проблему, изменив webpack.config.js.

моя новая конфигурация выглядит так:

До:

output: {
  path: path.join(__dirname, '/build/static/js'),
  filename: 'index.js'
},


devServer: {
  port: 3000
}

После:

output: {
  path: path.join(__dirname, '/build/static/js'),
  filename: 'index.js',
  publicPath: '/'
},


devServer: {
  historyApiFallback: true,
  port: 3000
}
person Sunil Kumar Singh    schedule 29.04.2020

Если вы запускаете его в Google Bucket, простое решение - рассмотреть index.html для страницы с ошибкой (404 не найден).

To do so:

  1. В списке сегментов найдите созданный сегмент.
  2. Щелкните меню переполнения сегмента (...), связанное с сегментом, и выберите Изменить конфигурацию веб-сайта.
  3. В диалоговом окне конфигурации веб-сайта также укажите главную страницу в качестве страницы с ошибкой.
person Sansei    schedule 16.07.2020
comment
Это не работает для меня - person Md. Parvez Alam; 16.12.2020

Используя экспресс на бэкэнде и React на фронтенде (без response-create-app) с охватом / маршрутизатором, отображается правильный компонент реагирования на маршрут охвата / маршрутизатора, а при нажатии ввода в адресной строке для ссылки меню устанавливается активный стиль. например http: // localhost: 8050 / pages. Пожалуйста, проверьте ниже или прямо в моем репозитории https://github.com/nickjohngray/staticbackeditor, все код есть.

Веб-пакет:

Настроить прокси. Это позволяет любым вызовам из порта 3000 (React) вызывать сервер, включая вызов для получения index.html или чего-либо еще в адресной строке при нажатии клавиши ввода. он также позволяет обращаться к маршруту API, чтобы получить данные JSON

например, await axios.post ('/ api / login', {email, pwd})

devServer: {
    port: 3000,
    open: true,
    proxy: {
      '/': 'http://localhost:8050',
    }
  }

Настройка экспресс-маршрутов

app.get('*', (req, res) => {
    console.log('sending index.html')
    res.sendFile(path.resolve('dist', 'index.html'))

});

Это будет соответствовать любому запросу от response, он просто возвращает страницу index.html, которая находится в моей папке dist, на этой странице, конечно же, есть более одностраничное приложение для реагирования. (обратите внимание, что над ним должны появиться любые другие маршруты, в моем случае это мои маршруты API)

Реагировать на маршруты

<Router>
    <Home path="/" />
    <Pages path="pages"/>
    <ErrorPage path="error"/>
    <Products path="products"/>
    <NotFound default />
</Router>

Эти маршруты определены в моем компоненте Layout, который загрузит соответствующий компонент при совпадении пути.

Конструктор макета React

 constructor(props) {
        super(props);


        this.props.changeURL({URL: globalHistory.location.pathname});
}

конструктор макета вызывается, как только он загружается. Здесь я вызываю свое действие changeURL, которое прослушивает мое меню, чтобы оно могло выделить правильный пункт меню, как показано ниже:

Код меню

<nav>
    {this.state.links.map( (link) =>
    <Link className={this.getActiveLinkClassName(link.path) } to={link.path}> 
      {link.name}
    </Link>)}            
</nav>
person nick    schedule 08.08.2020

В моем случае URL-адрес не загружался, когда я использовал в нем параметр.

В качестве быстрого исправления я добавляю <base href="<yourdomain/IP>"></base> под тегом файла index.html в папку сборки.

И это решило мою проблему.

person Diwakar Prasad    schedule 02.02.2021

У меня была такая же проблема, и это решение сработало у нас ..

Фон:

Мы размещаем несколько приложений на одном сервере. Когда мы обновляли, сервер не понимал, где искать наш индекс в папке dist для этого конкретного приложения. Вышеупомянутая ссылка приведет вас к тому, что сработало для нас ... Надеюсь, это поможет, поскольку мы потратили немало часов на поиск решения для наших нужд.

Мы используем:

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

мой webpack.config.js

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

мой index.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')
)

мой app.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!');
});
person J. Parrish    schedule 05.05.2017

Мне нравится такой способ справиться с этим. Попробуйте добавить: yourSPAPageRoute / * на стороне сервера, чтобы избавиться от этой проблемы.

Я выбрал этот подход, потому что даже собственный HTML5 History API не поддерживает правильное перенаправление при обновлении страницы (насколько мне известно).

Примечание: выбранный ответ уже касался этого, но я стараюсь быть более конкретным.

Экспресс-маршрут

Test - History API Протестировал и просто хотел поделиться этим.

Надеюсь, это поможет.

person Rehan    schedule 05.12.2018

Предположим, у вас есть следующее определение домашнего маршрута

<Route exact path="/" render={routeProps => (
   <Home routeProps={routeProps}/>
)}/>

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

В вашем домашнем компоненте вы можете перехватить запрос в событии ComponentWillMount,

const searchPath = this.props.routeProps.location.search;

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

Теперь вместо вызова / joblist по URL-адресу вы можете запросить /? Joblist, и компонент автоматически перенаправит запрос на / joblist (обратите внимание на дополнительный вопросительный знак в пути)

person user2674595    schedule 09.07.2019

Если вы приходите сюда и используете apache и у вас нет файла .htaccess, у меня сработал этот файл конфигурации:

sites-enabled/somedomain.com.conf

<VirtualHost *:80>
    ServerName somedomain.com
    ServerAlias *.somedomain.com
    DocumentRoot /www/somedomain.com/build

    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /www/somedomain.com/build/index.html [L,NC,QSA]

</VirtualHost>
person DevB2F    schedule 16.07.2019

Решение для Preact с preact-router

Работает с обновлением и прямым доступом

Для тех, кто узнал об этом через Google, вот демонстрация preact-router + история хеширования:

const { h, Component, render } = preact; /** @jsx h */
const { Router } = preactRouter;
const { createHashHistory } = History;
const App = () => (
    <div>
        <AddressBar />

        <Router history={createHashHistory()}>
            <div path="/">
                <p>
                    all paths in preact-router are still /normal/urls.
                    using hash history rewrites them to /#/hash/urls
                </p>
                Example: <a href="/page2">page 2</a>
            </div>
            <div path="/page2">
                <p>Page Two</p>
                <a href="/">back to home</a><br/>
            </div>
        </Router>
    </div>
);

jsfiddle

person keemor    schedule 05.10.2017

Я обнаружил обходной путь внешнего интерфейса, который не требует изменения чего-либо на сервере.

Допустим, ваш сайт - mysite.com и у вас есть React Route на mysite.com/about. В index.js, где вы монтируете свой компонент верхнего уровня, вы можете поместить другой маршрутизатор, например:

ReactDOM.render(
<Router>
    <div>
        <Route exact path="/" component={Home} />
        <Route exact path="/about"
            render={(props) => <Home {...props} refreshRout={"/about"}/>}
        />
    </div>
</Router>,

Я предполагаю, что у вас есть исходный маршрутизатор, расположенный где-то под компонентом верхнего уровня в виртуальной DOM. Вам также нужно поймать URL-адрес в ваших .urls, если вы используете Django, например:

urlpatterns = [
       path('about/', views.index),
]

Однако это будет зависеть от того, какой бэкэнд вы используете. Запрос mysite / about приведет вас к index.js (где вы монтируете компонент верхнего уровня), где вы можете использовать опору рендеринга Route, а не опору компонента, и передать '/ about' как опору в, в в этом примере компонент Home.

Внутри Home, в ловушке componentDidMount () или useEffect () выполните:

useEffect() {   
   //check that this.props.refreshRoute actually exists before executing the 
   //following line    
   this.props.history.replace(this.props.refreshRoute);
}

Я предположил, что ваш домашний компонент отображает что-то вроде:

<Router>
   <Route exact path="/" component={SomeComponent} />
   <Route path="/about" component={AboutComponent} />
</Router>

Кредит для (передать свойства компоненту, отображаемому с помощью React Router) о том, как передавать реквизиты компонентам в маршрутах.

person Stevie    schedule 28.07.2019

Я использую .Net Core 3.1 и только что добавил расширение MapFallbackToController:

Startup.cs

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");

        endpoints.MapFallbackToController("Index", "Home");
    });
person Sergio    schedule 08.05.2020

Другой способ запросить данные, даже если вы немедленно направляете URL-адреса, - это сделать так, чтобы каждый компонент имел метод, который вызывает эти последние параметры, такие как / about / test, а затем вашему государственному провайдеру, у вас есть функция который подключается к компоненту, с которым вы хотите запросить данные

person Vince    schedule 04.06.2020

Я использую режим React.js + Webpack. Я добавил параметр --history-api-fallback в файл package.json. Тогда обновление страницы работает правильно. Каждый раз, когда я меняю код, веб-страница обновляется автоматически.

"scripts": {
  "start": "rimraf build && cross-env NODE_ENV='development' webpack --mode development && cross-env NODE_ENV=development webpack-dev-server --history-api-fallback",
  ...
}
person NinjaDev    schedule 12.08.2020

Я знаю, что на этот вопрос был дан смертельный ответ, но он не решает проблему, когда вы хотите использовать маршрутизатор вашего браузера с прокси-доступом, когда вы не можете использовать root.

Для меня решение довольно простое.

скажем, у вас есть URL-адрес, указывающий на какой-то порт.

location / {
  proxy_pass http://127.0.0.1:30002/;
  proxy_set_header    Host            $host;
  port_in_redirect    off;
}

и теперь из-за браузера маршрутизатора суб-пути сломаны. Однако вы знаете, что такое подпути.

Решение этого? Для дополнительного пути /contact

# just copy paste.
location /contact/ {
  proxy_pass http://127.0.0.1:30002/;
  proxy_set_header    Host            $host;
}

Ничего другого, что я пробовал, не работает, но это простое исправление работает чертовски очаровательно.

person danieltan95    schedule 09.11.2020

Я столкнулся с этой проблемой в Electron, когда использовал React для интерфейса и react-router-dom для маршрутизации. Я заменил BrowserRouter на HashRouter, и это было исправлено. Вот простой пример

import {
  HashRouter as Router,
  Switch,
  Route,
} from "react-router-dom";
person Sanan Ali    schedule 03.06.2021
comment
нет необходимости использовать HashRouter, у меня есть решение для этого, недавно столкнулся с этой проблемой в проекте, вероятно, напишу ответ позже, когда у меня будет время - person Inzamam Malik; 10.07.2021
comment
конечно, хотелось бы узнать ваше решение. - person Sanan Ali; 12.07.2021

HashRouter будет простой реализацией,

import {HashRouter as Router,Switch,Route,Link} from 'react-router-dom';


  function App() {
  return (
    <Router>
        <Switch>
          <Route path="/" exact component={InitialComponent} />
          <Route path="/some" exact component={SomeOtherComponent} />
        </Switch>
      </Router>
  );
}

В браузере это будет примерно так - http: localhost: 3000 / # /, http: localhost: 3000 / # / some

person lakjeewa Wijebandara    schedule 10.07.2021

Это довольно просто, когда вы не можете получить ошибку 403 после обновления компонента dom. просто добавьте эту строку в конфигурацию вашего веб-пакета, 'historyApiFallback: true'. это savez весь мой день.

person praveenkumar s    schedule 02.01.2018

Полный маршрутизатор с примером (React Router v4):

Пример работы Пример Ознакомьтесь с проектом ниже.

response-router-4-example

После загрузки
1.) "npm install" в cmd для установки проекта
2.) "npm start" для запуска вашего реагирующего приложения.

Примечание. Для работы в Windows вам потребуется программное обеспечение Node js. В Mac OS установлен узел по умолчанию.

Ваше здоровье

person Muthu Kumar    schedule 29.01.2019