React-router и nginx

Вопрос или проблема

Я перевожу свое приложение на 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;
}

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

Вот несколько шагов, которые я предпринял, которые могут помочь, если вы только начинаете

  1. Как только вы в SSH, вам нужно вернуться к корню / с помощью cd .., затем вы должны быть в /
  2. Затем найдите .conf файл, обычно расположенный в /etc/nginx/sites-available/{название вашего сайта или default}, используйте cd, чтобы перейти к нему
  3. отредактируйте этот файл с помощью nano или vim, я использовал Vim так vi {ваш сайт.conf}
  4. Вот содержимое всего файла, который должен работать
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
}

Поиск решения

  1. Проверьте путь к корневой директории: Убедитесь, что путь, указанный в директиве root, соответствует месту, где находятся статические файлы вашего React-приложения (обычно это директория build, созданная с помощью команды npm run build).

  2. Обратите внимание на блок try_files: Важно, чтобы в директиве try_files был указан index.html в качестве резервного варианта для всех несуществующих маршрутов. Это позволяет вашему приложению загружать необходимый контент.

  3. Перезапустите Nginx: После внесения изменений в конфигурацию не забудьте перезапустить Nginx, чтобы изменения вступили в силу:

    sudo service nginx restart
  4. Отключите служебные конфигурации: Если вы используете Docker и ваши настройки не применяются, проверьте, не перезаписываются ли ваши конфигурации другими файлами в /etc/nginx/conf.d/. Если есть стандартный файл default.conf, подумайте о его удалении или переименовании, если он конфликтует с вашими настройками.

Заключение

Убедившись, что Nginx правильно настроен для обработки маршрутов вашего React-приложения, вы сможете избежать ошибок 404 и обеспечить плавную навигацию для своих пользователей. Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь обращаться за поддержкой или проводить отладку через логи Nginx, чтобы получить больше информации о возникших ошибках.

Оцените материал
Добавить комментарий

Капча загружается...