Вопрос или проблема
Я перевожу свое приложение на React с webpack-dev-server на nginx.
Когда я перехожу по корневому URL “localhost:8080/login”, я просто получаю 404, и в моем логе nginx я вижу, что он пытается получить:
my-nginx-container | 2017/05/12 21:07:01 [error] 6#6: *11 open() "/wwwroot/login" failed (2: Нет такого файла или каталога), client: 172.20.0.1, server: , request: "GET /login HTTP/1.1", host: "localhost:8080"
my-nginx-container | 172.20.0.1 - - [12/May/2017:21:07:01 +0000] "GET /login HTTP/1.1" 404 169 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0) Gecko/20100101 Firefox/53.0" "-"
Где мне искать решение?
Мой роутер в React выглядит так:
render(
<Provider store={store}>
<MuiThemeProvider>
<BrowserRouter history={history}>
<div>
Привет там p
<Route path="/login" component={Login} />
<App>
<Route path="/albums" component={Albums}/>
<Photos>
<Route path="/photos" component={SearchPhotos}/>
</Photos>
<div></div>
<Catalogs>
<Route path="/catalogs/list" component={CatalogList}/>
<Route path="/catalogs/new" component={NewCatalog}/>
<Route path="/catalogs/:id/photos/" component={CatalogPhotos}/>
<Route path="/catalogs/:id/photos/:photoId/card" component={PhotoCard}/>
</Catalogs>
</App>
</div>
</BrowserRouter>
</MuiThemeProvider>
</Provider>, app);
И мой файл nginx выглядит так:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
server {
listen 8080;
root /wwwroot;
location / {
root /wwwroot;
index index.html;
try_files $uri $uri/ /wwwroot/index.html;
}
}
}
ИЗМЕНЕНИЕ:
Я знаю, что большая часть настройки работает, потому что когда я перехожу по адресу localhost:8080, не будучи авторизованным, я также получаю страницу входа. Это не через перенаправление на localhost:8080/login – это какой-то код React.
Блок location в вашей конфигурации nginx должен быть:
location / {
try_files $uri /index.html;
}
Проблема в том, что запросы к файлу index.html работают, но вы не указываете nginx перенаправлять другие запросы к файлу index.html тоже.
Возможно, это не совсем тот случай, но для всех, кто работает с контейнером docker
для своего проекта react
с react-router
и webpack-dev-server
, в моем случае у меня было все необходимое в моем nginx.conf
:
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
location = / {
root /usr/share/nginx/html;
internal;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
Но все равно nginx не отправлял 404 ошибки на корень /
. После рассмотрения контейнера я заметил, что в /etc/nginx/conf.d/default.conf
есть какие-то конфигурации, которые каким-то образом переопределяли мои конфигурации, поэтому удаление этого файла в моем dockerfile
решило проблему:
...
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf # <= Эта строка решила мою проблему
COPY nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Вот мои решения
простое решение:
location / {
root /var/www/mysite;
try_files $uri /index.html;
}
больше не пытаться для типов, отличных от html:
location / {
root /var/www/mysite;
set $fallback_file /index.html;
if ($http_accept !~ text/html) {
set $fallback_file /null;
}
try_files $uri $fallback_file;
}
больше не пытаться для типов, отличных от html, и директорий (сделав try_files
совместимым с index
и/или autoindex
):
location / {
root /var/www/mysite;
index index.html;
autoindex on;
set $fallback_file /index.html;
if ($http_accept !~ text/html) {
set $fallback_file /null;
}
if ($uri ~ /$) {
set $fallback_file /null;
}
try_files $uri $fallback_file;
}
Вот решение, которое работает для меня на живом сервере:
Я просто следовал этому уроку и просто сконфигурировал блок location с базовой конфигурацией Nginx.
location / {
try_files $uri $uri/ /index.html;
}
Если вы обслуживаете из подкаталога (например, http://localhost:8080/jobs/):
используйте ваш блок / следующим образом:
server {
listen 8080;
server_name localhost;
absolute_redirect off;
root /usr/share/nginx/html;
index index.html;
location / {
expires 5m;
add_header Cache-Control "public";
try_files $uri $uri/ /jobs/index.html;
}
}
Блок location в вашей конфигурации nginx должен быть таким
location / {
root /path/to/root/dir;
index index.html index.htm;
try_files $uri $uri/ /index.html;
чтобы перенаправлять все запросы к index.html (вашему приложению React SPA).
И
В package.json
вашего проекта React добавьте "homepage":"http://your.website.go"
, чтобы сделать вложенные пути правильными для статических файлов.
{
"name": "React App",
"version": "0.0.0",
"homepage": "http://your.website.go",
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.1.1",
"react-scripts": "5.0.0",
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
}
Для меня ничего не работало, пока я не добавил директиву root. Это также работало для меня, используя обратный прокси для обращения к конечной точке /api/ веб-сервера.
location / {
root /usr/share/nginx/html;
try_files $uri /index.html;
}
У меня были некоторые проблемы с create-react-app, использующим сервис-воркеры и эту точную конфигурацию nginx. После публикации новой версии сайта сервис-воркер повторно загружал JS и отправлял файл index.html вместо 404. Поэтому моя обновленная версия конфигурации nginx выглядит так:
location / {
try_files $uri /index.html;
}
location /static/ {
try_files $uri =404;
}
Это гарантирует, что все, что находится в /static/, не вернет index.html.
Nginx попытается найти index.html в корне, если вы используете другую локацию, вам может потребоваться добавить его в инструкцию try_files:
Таким образом, вместо:
location /MyLocation {
root /var/www/html;
try_files $uri /index.html;
}
Вам следует сделать:
location /MyLocation {
root /var/www/html;
try_files $uri /MyLocation/index.html; # Убедитесь, что добавили папку в путь
}
Добавив MyLocation в try_files, вы заставляете nginx использовать правильный index.html при перенаправлении маршрутов.
Я столкнулся с такой же проблемой и думал, что это ошибка конфигурации, но нет. Я копировал файл конфигурации в папку /etc/nginx/conf.d/
. Это работает в разработке, но в сборочной версии вызывает эту проблему. Когда маршрут не удается, nginx не возвращается к index.
Просто скопируйте файл конфигурации в правильную папку: /etc/nginx/conf.d/default.conf
Пример инструкции Dockerfile:
COPY .docker/prod/nginx.conf /etc/nginx/conf.d/default.conf
Надеюсь, это поможет.
Я знаю, что на этот вопрос отвечали до бесконечности, но это не решает проблему, когда вы хотите использовать свой браузерный роутер с прокси, когда вы не можете использовать root.
Для меня решение довольно простое.
Скажем, у вас есть URL, который указывает на какой-то порт.
location / {
proxy_pass http://127.0.0.1:30002/;
proxy_set_header Host $host;
port_in_redirect off;
}
И теперь из-за маршрутизатора браузера подкаталоги сломаны. Однако вы знаете, какие подкаталоги есть.
Решение? Для подкаталога /contact
# просто копируйте и вставьте.
location /contact/ {
proxy_pass http://127.0.0.1:30002/;
proxy_set_header Host $host;
}
Ничто другое, что я пробовал, не работает, но этот простой фикс работает как часы.
Вот несколько шагов, которые я предпринял, которые могут помочь, если вы только начинаете
- Как только вы в SSH, вам нужно вернуться к корню
/
с помощьюcd ..
, затем вы должны быть в/
- Затем найдите .conf файл, обычно расположенный в
/etc/nginx/sites-available/{название вашего сайта или default}
, используйте cd, чтобы перейти к нему - отредактируйте этот файл с помощью
nano
илиvim
, я использовал Vim такvi {ваш сайт.conf}
- Вот содержимое всего файла, который должен работать
server {
listen 80;
server_name www.yourDomainName.com, yourDomainName.com;
location / {
root /usr/share/nginx/{путь к сборке вашего react проекта};
index index.html index.htm;
try_files $uri $uri/ /index.html;
passenger_enabled on;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
Добавьте файл с названием “Staticfile” в вашу домашнюю директорию и добавьте в этот файл следующий код.
pushstate: enabled
Я просто изменил:
проблема: —> try_files $uri $uri/index.html =404;
решение: —> try_files $uri $uri /index.html;
и проблема решена.
мой сайт сейчас работает без проблем
location / {
root /path/to/root/directory/of/staticfiles;
index index.html;
try_files $uri /index.html;
}
для приложения react не давайте директиву alias, вместо этого использование директивы root – это способ решения этой проблемы.
Ответ или решение
Основы настройки React с Nginx и маршрутизацией через react-router
При переходе с webpack-dev-server на Nginx для вашего React-приложения важно правильно настроить Nginx так, чтобы он корректно обрабатывал маршруты, определенные с помощью react-router.
Проблема
Как видно из вашего сообщения, при попытке доступа к URL, например localhost:8080/login
, вы получаете ошибку 404. Это происходит потому, что Nginx пытается найти физический файл по указанному пути (/wwwroot/login
), но не может его обнаружить, так как маршрутизация в React обрабатывается на стороне клиента.
Решение
Чтобы Nginx корректно обрабатывал такие запросы, настройте блок location
в конфигурации Nginx так, чтобы он перенаправлял все запросы, которые не соответствуют существующим файлам, на ваш index.html
файл. Это позволит react-router управлять маршрутизацией на стороне клиента.
Пример конфигурации Nginx
Вот пример конфигурации, который должен решить вашу проблему:
server {
listen 8080;
server_name localhost;
root /wwwroot; # Убедитесь, что здесь правильный путь к вашей сборке React
location / {
try_files $uri $uri/ /index.html; # Перенаправляем на index.html для обработки маршрутов React
}
error_page 404 /index.html; # В случае 404 также перенаправлять на index.html
}
Поиск решения
-
Проверьте путь к корневой директории: Убедитесь, что путь, указанный в директиве
root
, соответствует месту, где находятся статические файлы вашего React-приложения (обычно это директорияbuild
, созданная с помощью командыnpm run build
). -
Обратите внимание на блок try_files: Важно, чтобы в директиве
try_files
был указанindex.html
в качестве резервного варианта для всех несуществующих маршрутов. Это позволяет вашему приложению загружать необходимый контент. -
Перезапустите Nginx: После внесения изменений в конфигурацию не забудьте перезапустить Nginx, чтобы изменения вступили в силу:
sudo service nginx restart
-
Отключите служебные конфигурации: Если вы используете Docker и ваши настройки не применяются, проверьте, не перезаписываются ли ваши конфигурации другими файлами в
/etc/nginx/conf.d/
. Если есть стандартный файлdefault.conf
, подумайте о его удалении или переименовании, если он конфликтует с вашими настройками.
Заключение
Убедившись, что Nginx правильно настроен для обработки маршрутов вашего React-приложения, вы сможете избежать ошибок 404 и обеспечить плавную навигацию для своих пользователей. Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за поддержкой или проводить отладку через логи Nginx, чтобы получить больше информации о возникших ошибках.