React-router i nginx

109

Przenoszę moją aplikację React z serwera webpack-dev-server na nginx.

Kiedy przechodzę do głównego adresu URL „localhost: 8080 / login”, po prostu otrzymuję 404 iw moim dzienniku nginx widzę, że próbuje uzyskać:

my-nginx-container | 2017/05/12 21:07:01 [error] 6#6: *11 open() "/wwwroot/login" failed (2: No such file or directory), 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" "-"

Gdzie mam szukać poprawki?

Mój router reaguje tak:

render(

  <Provider store={store}>
    <MuiThemeProvider>
      <BrowserRouter history={history}>
        <div>
          Hello there 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);

A mój plik nginx taki:

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


    }
}

EDYTOWAĆ:

Wiem, że większość konfiguracji działa, ponieważ kiedy przechodzę do localhost: 8080 bez zalogowania się, otrzymuję również stronę logowania. nie dzieje się tak przez przekierowanie na localhost: 8080 / login - to jakiś kod reakcji.

jaskółka oknówka
źródło
1
Parametry try_filespowinny być identyfikatorami URI, a nie nazwami ścieżek. Spróbuj:try_files $uri $uri/ /index.html;
Richard Smith
@RichardSmith OK ... Widziałem to jako ścieżkę do pliku index.html. Próbowałem zmienić to na to, co sugerowałeś - ale otrzymałem ten sam wynik. ## / wwwroot / login ”nie powiodło się (2: Brak takiego pliku lub katalogu) ## czy masz inne sugestie. Zagłębię się w to jutro ...
martin
@martin, czy udało Ci się już to rozwiązać? Widzimy to samo, ale mamy już tam linię try_files.
Billy Ferguson,

Odpowiedzi:

243

Blok lokalizacji w twojej konfiguracji nginx powinien być:

location / {
  try_files $uri /index.html;
}

Problem polega na tym, że żądania wysyłane do pliku index.html działają, ale obecnie nie mówisz nginx, aby przekazywał również inne żądania do pliku index.html.

Toby
źródło
8
Sprawdź to, aby uzyskać bardziej zaawansowaną konfigurację (buforowanie, 404 w przypadku brakujących plików .js, .css itp.). Gkedge.gitbooks.io/react-router-in-the-real/content/nginx.html
Gianfranco str.
Wygląda na to, że React Router w ogóle nie powinien powodować ruchu w obie strony do serwera ... czy można to lokalnie utrudniać?
Scotty H
Jeśli nginx nie kieruje żądania do pliku index.html, to JS wewnątrz React Router nigdy nie będzie nawet świadomy żądania. Ta odpowiedź kieruje wszystkie żądania do React, pozwalając React Router na obsługę wszystkich żądań.
Toby
Ważne jest również, aby użyć domyślnego ustawienia strony głównej w package.json, który używa katalogu głównego serwera. Ustawiłem go na '.', (Użyj ścieżek względnych), ale potem nginx próbował obsłużyć /custompath/static/main.js, co oczywiście się nie powiedzie, dając niedziałającą witrynę.
boerre
tylko uwaga, upewnij się, że konfiguracja jest faktycznie ładowana, moja była w konflikcie z wartością domyślną i po prostu została pominięta. westchnienie
4c74356b41
18

Oto moje rozwiązania

proste wypróbowanie:

location / {
    root /var/www/mysite;
    try_files $uri /index.html;
}

koniec z próbami wyszukiwania typów innych niż 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;
}

koniec z próbami wyszukiwania typów i katalogów innych niż HTML ( try_fileszapewnienie zgodności z indexi / lub 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;
}
fuweichin
źródło
9

Może to nie jest dokładny przypadek tutaj, ale dla każdego, kto jest uruchomiona dockerpojemnik dla swojego reactprojektu z react-routeri webpack-dev-server, w moim przypadku miałem wszystko, co potrzebne w moim 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;
    }
  }

Ale nadal nginx nie wyśle ​​błędów 404 do katalogu głównego /. Po przejrzeniu kontenera zauważyłem, że jest kilka konfiguracji, /etc/nginx/conf.d/default.confktóre w jakiś sposób nadpisują moje konfiguracje, więc usunięcie tego pliku w moim dockerfilerozwiązało problem:

...
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf  # <= This line solved my issue
COPY nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Alex Jolig
źródło
1
Uratowałeś mi dzień!
Bilal Hussain
4

Oto rozwiązanie, które działa dla mnie na serwerze live:

Właśnie skorzystałem z tego samouczka i przy podstawowej konfiguracji Nginx po prostu skonfigurowałem blok lokalizacji.

location / {
    try_files $uri $uri/ /index.html;
}
Fatema T. Zuhora
źródło
0

Dla mnie nic nie działało, dopóki nie dodałem dyrektywy roota. To zadziałało dla mnie również przy użyciu zwrotnego serwera proxy do trafienia w punkt końcowy / api / webserver.

location / {
    root   /usr/share/nginx/html;
    try_files $uri /index.html;
}
Jazzepi
źródło
0

Miałem do czynienia z tym samym problemem i pomyślałem, że to błąd conf, ale nie. Kopiowałem plik conf do/etc/nginx/conf.d/ folderu. To działa w programowaniu, ale w wersji kompilacji powoduje ten problem. Gdy trasa nie powiedzie się, nginx nie powraca do index.

Po prostu skopiuj plik conf do odpowiedniego folderu: /etc/nginx/conf.d/default.conf

Przykładowa instrukcja Dockerfile: COPY .docker/prod/nginx.conf /etc/nginx/conf.d/default.conf

Mam nadzieję, że to pomoże.

diogopalhais
źródło
-1
location / {
    root /path/to/root/directory/of/staticfiles;
    index index.html;
    try_files $uri /index.html;
}
sagarpatidar
źródło
Odpowiedzi zawierające tylko kod są odradzane w przypadku przepełnienia stosu, ponieważ nie wyjaśniają, w jaki sposób rozwiązuje problem. Edytuj swoją odpowiedź, aby wyjaśnić, co robi ten kod i jak ulepsza istniejące odpowiedzi, za które głosowano, tak, aby była przydatna dla OP, a także dla innych użytkowników z podobnymi problemami.
FluffyKitten