React-Router und Nginx

107

Ich stelle meine Reaktions-App von Webpack-Dev-Server auf Nginx um.

Wenn ich zur Root-URL "localhost: 8080 / login" gehe, erhalte ich einfach eine 404 und in meinem Nginx-Protokoll sehe ich, dass versucht wird:

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

Wo soll ich nach einer Lösung suchen?

Mein Router, der reagiert, sieht folgendermaßen aus:

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

Und meine Nginx-Datei sieht so aus:

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


    }
}

BEARBEITEN:

Ich weiß, dass der Großteil des Setups funktioniert, denn wenn ich zu localhost: 8080 gehe, ohne angemeldet zu sein, erhalte ich auch die Anmeldeseite. Dies geschieht nicht durch eine Umleitung zu localhost: 8080 / login - es handelt sich um einen Reaktionscode.

Martin
quelle
1
Die Parameter try_filessollten URIs und keine Pfadnamen sein. Versuchen Sie:try_files $uri $uri/ /index.html;
Richard Smith
@RichardSmith OK ... Ich habe es als Pfadnamen für die Datei index.html gesehen. Ich habe versucht, es auf das zu ändern, was Sie vorgeschlagen haben - aber das gleiche Ergebnis erzielt. ## / wwwroot / login "fehlgeschlagen (2: Keine solche Datei oder kein solches Verzeichnis) ## Haben Sie andere Vorschläge. Ich werde heute Abend darauf eingehen ...
Martin
@martin hast du das schon lösen können? Wir sehen dasselbe, hatten aber bereits die Zeile try_files drin.
Billy Ferguson

Antworten:

238

Der Standortblock in Ihrer Nginx-Konfiguration sollte sein:

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

Das Problem ist, dass Anforderungen an die Datei index.html funktionieren, aber Sie weisen nginx derzeit nicht an, andere Anforderungen auch an die Datei index.html weiterzuleiten.

Toby
quelle
8
Überprüfen Sie dies für eine erweiterte Konfiguration (Caching, 404 für fehlende .js, .css-Dateien usw.). Gkedge.gitbooks.io/react-router-in-the-real/content/nginx.html
Gianfranco S.
Es scheint, dass React Router überhaupt keinen Roundtrip zum Server verursachen sollte ... kann dies lokal verhindert werden?
Scotty H
Wenn nginx die Anforderung nicht an die Datei index.html weiterleitet, wird der JS in React Router die Anforderung nicht einmal bemerken. Diese Antwort leitet alle Anforderungen an React weiter, sodass React Router alle Anforderungen verarbeiten kann.
Toby
Es ist auch wichtig, die Standardeinstellung für die Startseite in package.json zu verwenden, die das Serverstammverzeichnis verwendet. Ich hatte es auf '.' Gesetzt (relative Pfade verwenden), aber dann versuchte nginx, /custompath/static/main.js zu bedienen, was offensichtlich fehlschlagen wird und eine nicht funktionierende Site ergibt.
Boerre
Nur ein Kopf hoch, stellen Sie sicher, dass Ihre Konfiguration tatsächlich geladen wird, meine mit der Standardeinstellung in Konflikt stand und nur übersprungen wurde. Seufzer
4c74356b41
18

Hier sind meine Lösungen

einfacher Versuch:

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

Kein Versuch mehr für Nicht-HTML-Typen:

location / {
    root /var/www/mysite;
    set $fallback_file /index.html;
    if ($http_accept !~ text/html) {
        set $fallback_file /null;
    }
    try_files $uri $fallback_file;
}

Sie müssen nicht mehr nach Nicht-HTML-Typen und -Verzeichnissen suchen ( try_fileskompatibel mit indexund / oder 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
quelle
9

Vielleicht ist dies hier nicht der genaue Fall, aber für jeden, der einen dockerContainer für sein reactProjekt mit betreibt, react-routerund webpack-dev-serverin meinem Fall hatte ich alles, was ich brauchte 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;
    }
  }

Trotzdem würde Nginx keine 404 Fehler an die Wurzel senden /. Nachdem ich in den Container /etc/nginx/conf.d/default.confgeschaut hatte, bemerkte ich, dass es einige Konfigurationen gibt, die meine Konfigurationen irgendwie überschreiben würden. Das Löschen dieser Datei in meinem hat dockerfiledas Problem gelöst:

...
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
quelle
1
Du hast meinen Tag gerettet!
Bilal Hussain
4

Hier ist die Lösung, die für mich auf dem Live-Server funktioniert:

Ich habe gerade dieses Tutorial befolgt und mit der grundlegenden Nginx-Konfiguration einfach den Standortblock konfiguriert.

location / {
    try_files $uri $uri/ /index.html;
}
Fatema T. Zuhora
quelle
0

Für mich hat nichts funktioniert, bis ich eine Root-Direktive hinzugefügt habe. Dies funktionierte bei mir auch mit einem Reverse-Proxy, um einen / api / webserver-Endpunkt zu erreichen.

location / {
    root   /usr/share/nginx/html;
    try_files $uri /index.html;
}
Jazzepi
quelle
0

Ich hatte mit dem gleichen Problem zu tun und dachte, das sei ein Conf-Fehler, aber nein. Ich habe die conf-Datei in den /etc/nginx/conf.d/Ordner kopiert . Das funktioniert in dev, aber in der Build-Version verursacht dieses Problem. Wenn die Route fehlschlägt, greift der Nginx nicht auf den Index zurück.

Kopieren Sie einfach die conf-Datei in den richtigen Ordner: /etc/nginx/conf.d/default.conf

Beispiel für eine Dockerfile-Anweisung: COPY .docker/prod/nginx.conf /etc/nginx/conf.d/default.conf

Ich hoffe es hilft.

Diogopalhais
quelle