URL-адреса React-маршрутизатора не работают при обновлении или записи вручную
Я использую React-роутер, и он отлично работает, пока я нажимаю на кнопки ссылок, но когда я обновляю свою веб-страницу, она не загружает то, что я хочу.
Например, я нахожусь в 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);
});
65 ответов
Глядя на комментарии к принятому ответу и общий характер этого вопроса ("не работает"), я подумал, что это может быть хорошим местом для некоторых общих объяснений по вопросам, связанным с этим. Таким образом, этот ответ предназначен в качестве справочной информации / разработки по конкретному варианту использования ОП. Пожалуйста, потерпите меня.
Сторона сервера против стороны клиента
Первая важная вещь, которую нужно понять, это то, что теперь есть 2 места, где URL интерпретируется, тогда как раньше было "1" в "старые времена". В прошлом, когда жизнь была простой, какой-то пользователь отправлял запрос на http://example.com/about
на сервер, который проверил часть пути URL-адреса, определил, что пользователь запрашивает страницу о программе, а затем отправил обратно эту страницу.
С маршрутизацией на стороне клиента, которую предоставляет 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 выполняет маршрутизацию за вас, но они терпят неудачу на стороне сервера, если вы не заставите свой сервер их понять.
Объединение серверной и клиентской маршрутизации
Если вы хотите http://example.com/about
URL-адрес для работы как на стороне сервера, так и на стороне клиента, для него необходимо настроить маршруты как на стороне сервера, так и на стороне клиента. Имеет смысл правильно?
И вот тут начинается ваш выбор. Решения варьируются от полного обхода проблемы через универсальный маршрут, который возвращает загрузочный HTML, до полного изоморфного подхода, когда и сервер, и клиент выполняют один и тот же код JS.
,
Обход проблемы в целом: Hash History
С помощью Hash History вместо истории браузера ваш URL для страницы about будет выглядеть примерно так: http://example.com/#/about
Часть после хеша (#
) символ не отправляется на сервер. Так сервер только видит http://example.com/
и отправляет страницу индекса, как и ожидалось. React-Router подберет #/about
часть и покажи правильную страницу.
Недостатки:
- "уродливые" URL
- При таком подходе рендеринг на стороне сервера невозможен. Что касается поисковой оптимизации (SEO), ваш сайт состоит из одной страницы, на которой почти нет контента.
,
Вместилище разнообразных предметов
При таком подходе вы используете историю браузеров, но просто настраиваете ловушку на сервере, который отправляет /*
в index.html
, эффективно предоставляя вам ту же ситуацию, что и с Hash History. Тем не менее, у вас есть чистые URL, и вы могли бы улучшить эту схему позже, не делая недействительными все избранное вашего пользователя.
Недостатки:
- Более сложный в настройке
- Все еще нет хорошего SEO
,
Гибридный
В гибридном подходе вы расширяете общий сценарий, добавляя конкретные сценарии для определенных маршрутов. Вы можете сделать несколько простых PHP-скриптов, чтобы вернуть наиболее важные страницы вашего сайта с включенным контентом, чтобы робот Googlebot мог хотя бы увидеть, что находится на вашей странице.
Недостатки:
- Еще сложнее настроить
- Только хороший SEO для тех маршрутов, которые вы предоставляете специальную обработку
- Дублирование кода для рендеринга контента на сервере и клиенте
,
изоморфный
Что если мы используем Node JS в качестве нашего сервера, чтобы мы могли запускать один и тот же код JS на обоих концах? Теперь у нас есть все наши маршруты, определенные в одной конфигурации реакции-маршрутизатора, и нам не нужно дублировать код рендеринга. Это, так сказать, "Святой Грааль". Сервер отправляет ту же самую разметку, которую мы получили бы в случае перехода страницы на клиенте. Это решение является оптимальным с точки зрения SEO.
Недостатки:
- Сервер должен (быть в состоянии) запустить JS. Я экспериментировал с Java icw Nashorn, но он не работает для меня. На практике это в основном означает, что вы должны использовать сервер на базе Node JS.
- Многие сложные экологические проблемы (используя
window
на стороне сервера и т. д.) - Крутая кривая обучения
,
Какой я должен использовать?
Выберите тот, который вы можете сойти с рук. Лично я думаю, что все достаточно просто, чтобы настроить это, что будет моим минимумом. Эта настройка позволяет вам улучшать вещи с течением времени. Если вы уже используете Node JS в качестве серверной платформы, я бы определенно занялся созданием изоморфного приложения. Да, сначала это сложно, но как только вы освоитесь, это на самом деле очень элегантное решение проблемы.
В общем, для меня это было бы решающим фактором. Если бы мой сервер работал на Node JS, я бы стал изоморфным, в противном случае я бы выбрал решение Catch-all и просто расширил его (гибридное решение), когда время прогрессирует, а требования SEO требуют этого.
Если вы хотите узнать больше об изоморфном (также называемом "универсальным") рендеринге с помощью React, есть несколько хороших учебников по этому вопросу:
- Реагируйте на будущее с помощью изоморфных приложений
- Боль и радость создания изоморфных приложений в ReactJS
- Как реализовать Node + Реагировать на изоморфный JavaScript и почему это важно
Кроме того, для начала я рекомендую взглянуть на некоторые стартовые наборы. Выберите тот, который соответствует вашему выбору для технологического стека (помните, React - это просто V в MVC, вам нужно больше вещей для создания полноценного приложения). Начнем с просмотра того, что опубликовано самим Facebook:
Или выберите один из множества сообществ. Теперь есть хороший сайт, который пытается проиндексировать их все:
Я начал с этого:
В настоящее время я использую самодельную версию универсального рендеринга, которая была вдохновлена двумя вышеприведенными стартовыми наборами, но сейчас они устарели.
Удачи в вашем квесте!
Вы можете изменить свой htaccess и вставить это:
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
я использую react: "^15.3.2"
, react-router: "^3.0.0"
, history: "^4.3.0"
,
Все ответы здесь чрезвычайно полезны, для меня работало то, что я настроил мой сервер Webpack для ожидания маршрутов.
devServer: {
historyApiFallback: true,
contentBase: './',
hot: true
},
HistoryApiFallback - это то, что исправило эту проблему для меня. Теперь маршрутизация работает правильно, и я могу обновить страницу или ввести URL-адрес напрямую. Не нужно беспокоиться об обходах на вашем сервере узлов. Этот ответ, очевидно, работает только при использовании веб-пакета.
РЕДАКТИРОВАТЬ: см. Мой ответ здесь для более подробной причины, почему это необходимо: /questions/19499587/react-router-20-browserhistory-ne-rabotaet-pri-obnovlenii/19499604#19499604
Для пользователей React Router V4:
Если вы попытаетесь решить эту проблему с помощью техники Hash History, упомянутой в других ответах, обратите внимание, что
<Router history={hashHistory} >
не работает в V4, пожалуйста, используйте HashRouter
вместо:
import { HashRouter } from 'react-router-dom'
<HashRouter>
<App/>
</HashRouter>
Ссылка: https://reacttraining.com/react-router/web/api/HashRouter
Я использовал create-реагировать-приложение, чтобы сделать веб-сайт только что и тот же вопрос, представленный здесь. я использую 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 и может быть найдено здесь
В вашем 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
это важная часть
Если вы используете приложение Create React:
Тем не менее, эта проблема отлично подходит для решений для многих основных хостинговых платформ, которые вы можете найти ЗДЕСЬ на странице Create React App. Например, я использую React Router v4 и Netlify для своего кода веб-интерфейса. Все, что нужно, это добавить 1 файл в мою общую папку ("_redirects") и одну строку кода в этом файле:
/* /index.html 200
Теперь мой веб-сайт правильно отображает пути, такие как mysite.com/pricing, при входе в браузер или при обновлении.
Маршрутизатор можно вызывать двумя различными способами, в зависимости от того, происходит ли навигация на клиенте или на сервере. Он настроен для работы на стороне клиента. Ключевым параметром является второй по отношению к методу выполнения местоположение.
Когда вы используете компонент React Router Link, он блокирует навигацию в браузере и вызывает transitionTo для выполнения навигации на стороне клиента. Вы используете HistoryLocation, поэтому он использует API истории HTML5, чтобы завершить иллюзию навигации, имитируя новый URL в адресной строке. Если вы используете старые браузеры, это не сработает. Вам нужно будет использовать компонент HashLocation.
Когда вы нажимаете "обновить", вы обходите весь код React и React Router. Сервер получает запрос на /joblist
и это должно что-то вернуть. На сервере вам нужно передать путь, который был запрошен run
метод для того, чтобы сделать правильный вид. Вы можете использовать ту же карту маршрута, но вам, вероятно, понадобится другой вызов Router.run
, Как указывает Чарльз, вы можете использовать переписывание URL для этого. Другой вариант - использовать сервер node.js для обработки всех запросов и передачи значения пути в качестве аргумента location.
В экспрессе, например, это может выглядеть так:
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 на стороне сервера по мере необходимости.
Если вы используете приложение реакции с помощью AWS Static S3 Hosting и CloudFront
Эта проблема возникла из-за того, что CloudFront ответил сообщением 403 "Отказано в доступе", так как ожидалось, что / некоторый / другой / путь будет существовать в моей папке S3, но этот путь существует только внутри маршрутизации React с реакции-маршрутизатором.
Решением было настроить правило распространения страниц ошибок. Перейдите в настройки CloudFront и выберите свой дистрибутив. Далее перейдите на вкладку "Страницы ошибок". Нажмите "Создать пользовательский ответ об ошибке" и добавьте запись для 403, так как это код ошибки, который мы получаем. Установите для параметра "Путь к странице ответа" значение /index.html, а для кода состояния - значение 200. Конечный результат поражает своей простотой. Страница индекса обслуживается, но URL-адрес сохраняется в браузере, поэтому, как только приложение реакции загружается, оно обнаруживает путь URL-адреса и переходит к нужному маршруту.
Если вы размещаете свое приложение реагирования в 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, и нет необходимости использовать историю хешей.
Это может решить вашу проблему
Я также столкнулся с той же проблемой в приложении 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-адресе. лайк
localhost/#/home localhost/#/aboutus
Решение 2. Без тега # с помощью browserHistory,
Установите вашу историю = {browserHistory} в вашем маршрутизаторе, теперь соберите ее с помощью sudo npm run build.
Вам нужно создать файл "conf" для решения страницы 404 not found, файл conf должен быть таким.
откройте свой терминал введите ниже команды
cd /etc/apache2/sites-available ls nano sample.conf Добавьте в него содержимое, представленное ниже.
<VirtualHost *:80>
ServerAdmin admin@0.0.0.0
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 или restart.
затем откройте папку localhost/build и добавьте файл.htaccess с содержанием ниже.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ / [L,QSA]
Теперь приложение работает нормально.
Примечание: измените 0.0.0.0 ip на ваш локальный IP-адрес.
Если есть какие-либо сомнения по этому поводу, не стесняйтесь поднять комментарий.
Я надеюсь, что это полезно для других.
Добавьте это в webpack.congif.js
devServer: {
historyApiFallback: true
}
Производственный стек: React, React Router v4, BrowswerRouter, Express, Nginx
1) Пользователь 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;
}
У сервера Webpack Dev есть возможность включить это. Открыть package.json
и добавить --history-api-fallback
, Это решение работало для меня.
https://github.com/reactjs/react-router-tutorial/tree/master/lessons/10-clean-urls
Попробуйте добавить файл ".htaccess" в общую папку с помощью приведенного ниже кода.
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html [L]
Если вы используете firebase, все, что вам нужно сделать, это убедиться, что у вас есть свойство rewrites в файле firebase.json в корне вашего приложения (в разделе хостинга).
Например:
{
"hosting": {
"rewrites": [{
"source":"**",
"destination": "/index.html"
}]
}
}
Надеюсь, что это сэкономит кому-то еще кучу разочарования и потраченного времени.
Удачного кодирования...
Дальнейшее чтение по теме:
https://firebase.google.com/docs/hosting/full-config
Firebase CLI: "Настроить как одностраничное приложение (переписать все URL в /index.html)"
Действительно потрясающие ответы уже !! Но если вы размещаете с помощью nginx и нуждаетесь в быстром исправлении ... добавьте следующую строку в свою конфигурацию nginx внутри блока местоположения
location / {
try_files $uri /index.html;
}
Я нашел решение для моего 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/173878f9d67055bfef63449fa7136042
Если вы используете Express или какой-либо другой фреймворк в бэкэнде, вы можете добавить аналогичную конфигурацию, как показано ниже, и проверить открытый путь Webpack в конфигурации, он должен работать нормально даже при перезагрузке, если вы используете BrowserRouter
` expressApp.get('/*', (request, response) => {
response.sendFile(path.join(__dirname, '../public/index.html'));
});`
Для тех, кто использует 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, поскольку страница недоступна. Сделайте следующее:
- Откройте IIS
- Разверните Сервер, затем откройте папку "Сайты".
- Нажмите на сайт / приложение
- Перейти на страницы ошибок
- Откройте пункт состояния ошибки 404 в списке
- Вместо параметра "Вставить содержимое из статического файла в ответ об ошибке" измените его на "Выполнить URL на этом сайте" и добавьте "/" значение косой черты в URL.
И теперь это будет работать нормально.
Я надеюсь, что это помогает.:-)
Если у вас есть запасной вариант вашего index.html, убедитесь, что в вашем файле index.html у вас есть это:
<script>
System.config({ baseURL: '/' });
</script>
Это может отличаться от проекта к проекту.
С помощью 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();
кому:
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();
Вы можете попробовать все это прочитать, хотя это не мое:
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, в котором вы можете указать путь к подкаталогу:
С этого момента каждый маршрут, подобный / contacts, будет приводить к URL-адресу, например http://myapp.com/the-app/contacts.
Исправление ошибки "невозможно получить /URL" при обновлении или при непосредственном вызове URL.
Сконфигурируйте ваш webpack.config.js так, чтобы он ожидал, что по данной ссылке будут проходить такие маршруты
module.exports = {
entry: './app/index.js',
output: {
path: path.join(__dirname, '/bundle'),
filename: 'index_bundle.js',
publicPath: '/'
},
Если вы используете команду "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 для обработки реагирующим маршрутизатором. Ниже показан пример контроллера, написанного с использованием spring.
@Controller
public class ForwardingController {
@RequestMapping("/<any end point name>/{path:[^\\.]+}/**")
public String forward(HttpServletRequest httpServletRequest) {
return "forward:/";
}
}
например, если мы возьмем конечную точку REST back-end api как "abc" (http://localhost:8080/abc/**), любой запрос, поступающий на эту конечную точку, будет перенаправлен на реагирующее приложение (файл index.html) и реагировать на маршрутизатор обработает это послесловие.
Я использую ASP.NET Core и React . Решением проблемы ручной маршрутизации и обновления маршрутов в производственной среде было создание файла в корне основного проекта ASP.NET Core, который будет настраивать маршрутизацию на производственном сервере.
Расположение файла внутри проекта:
Содержание
web.config
файл:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Rewrite Text Requests" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_METHOD}" pattern="^GET$" />
<add input="{HTTP_ACCEPT}" pattern="^text/html" />
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Я решил эту проблему, изменив 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
}
Эта тема немного устарела и решаема, но я хотел бы предложить вам простое, ясное и лучшее решение. Это работает, если вы используете веб-сервер.
Каждый веб-сервер имеет возможность перенаправить пользователя на страницу ошибки в случае 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.
Вот и все, больше никаких магических потребностей:)
Я столкнулся с этой проблемой в Electron, когда использовал React для интерфейса и
react-router-dom
для маршрутизации. Я заменил
BrowserRouter
с участием
HashRouter
и это было исправлено. Вот простой пример
import {
HashRouter as Router,
Switch,
Route,
} from "react-router-dom";
Я пока не использую рендеринг на стороне сервера, но столкнулся с той же проблемой, что и операционная система, где, как мне показалось, в большинстве случаев Link работал нормально, но мне не удавалось получить параметр Я запишу здесь свое решение, чтобы посмотреть, поможет ли оно кому-нибудь.
Мой основной JSX содержит это:
<Route onEnter={requireLogin} path="detail/:id" component={ModelDetail} />
Это отлично работает для первой подходящей ссылки, но когда изменяется: id <Link>
В выражениях, вложенных на страницу сведений о модели, URL-адрес изменяется на панели браузера, но содержимое страницы изначально не изменялось, чтобы отражать связанную модель.
Беда в том, что я использовал props.params.id
установить модель в componentDidMount
, Компонент монтируется только один раз, так что это означает, что первая модель - это та, которая прикрепляется на странице, а последующие ссылки изменяют реквизиты, но оставляют страницу неизменной.
Установка модели в состояние компонента в обоих componentDidMount
И в componentWillReceiveProps
(где это основано на следующих подпорках) решает проблему, и содержание страницы изменяется, чтобы отразить желаемую модель.