React-router et nginx

109

Je suis en train de faire la transition de mon application react de webpack-dev-server vers nginx.

Quand je vais à l'url racine "localhost: 8080 / login", j'obtiens simplement un 404 et dans mon journal nginx je vois qu'il essaie d'obtenir:

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

Où dois-je chercher une solution?

Mon routeur bit en réaction ressemble à ceci:

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

Et mon fichier nginx comme ceci:

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


    }
}

ÉDITER:

Je sais que la plupart de l'installation fonctionne parce que lorsque je vais sur localhost: 8080 sans être connecté, j'obtiens également la page de connexion. ce n'est pas par une redirection vers localhost: 8080 / login - c'est du code de réaction.

Martin
la source
1
Les paramètres try_filesdoivent être des URI et non des chemins. Essayez:try_files $uri $uri/ /index.html;
Richard Smith
@RichardSmith OK ... Je l'ai vu comme le chemin d'accès au fichier index.html. J'ai essayé de le changer pour ce que vous avez suggéré - mais en obtenant le même résultat. ## / wwwroot / login "a échoué (2: aucun fichier ou répertoire de ce type) ## avez-vous d'autres suggestions. Je vais y plonger tonite ...
martin
@martin avez-vous réussi à résoudre ce problème? Nous voyons la même chose, mais il y avait déjà la ligne try_files.
Billy Ferguson

Réponses:

243

Le bloc d'emplacement dans votre configuration nginx doit être:

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

Le problème est que les requêtes adressées au fichier index.html fonctionnent, mais vous ne dites pas actuellement à nginx de transférer également d'autres requêtes vers le fichier index.html.

Toby
la source
8
Vérifiez ceci pour une configuration plus avancée (mise en cache, 404 pour les fichiers .js, .css manquants, etc.) gkedge.gitbooks.io/react-router-in-the-real/content/nginx.html
Gianfranco P.
Il semble que React Router ne devrait pas du tout provoquer un aller-retour vers le serveur ... cela peut-il être bloqué localement?
Scotty H
si nginx n'achemine pas la requête vers le fichier index.html, alors le JS à l'intérieur du React Router ne sera même jamais informé de la requête. Cette réponse achemine toutes les demandes vers React, permettant à React Router de gérer toutes les demandes.
Toby
Il est également important d'utiliser le paramètre de page d'accueil par défaut dans package.json, qui utilise la racine du serveur. Je l'avais mis à '.', (Utiliser des chemins relatifs), mais ensuite nginx a essayé de servir /custompath/static/main.js, ce qui échouera évidemment, donnant un site non fonctionnel.
boerre
juste un avertissement, assurez-vous que votre configuration est effectivement en cours de chargement, la mienne était en conflit avec la valeur par défaut et simplement ignorée. soupir
4c74356b41
18

Voici mes solutions

essai simple:

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

plus d'essayer pour les types non-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;
}

plus besoin d'essayer des types et des répertoires non html (rendant try_filescompatible avec indexet / ou 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
la source
9

Ce n'est peut-être pas le cas exact ici, mais pour tous ceux qui exécutent un dockerconteneur pour leur reactprojet avec react-routeret webpack-dev-server, dans mon cas, j'avais tout ce dont j'avais besoin dans mon 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;
    }
  }

Mais nginx n'enverrait toujours pas 404 erreurs à la racine /. Après avoir regardé dans le conteneur, j'ai remarqué qu'il y avait des configurations dans /etc/nginx/conf.d/default.conflesquelles remplacer mes configurations d'une manière ou d'une autre, donc la suppression de ce fichier dans mon a dockerfilerésolu le problème:

...
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
la source
1
Tu as sauvé ma journée!
Bilal Hussain le
4

Voici la solution qui fonctionne pour moi dans le serveur live:

Je viens de suivre ce tutoriel et avec la configuration de base de Nginx, je viens de configurer le bloc d'emplacement.

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

Pour moi, rien n'a fonctionné jusqu'à ce que j'aie ajouté une directive racine. Cela a fonctionné pour moi également en utilisant un proxy inverse pour atteindre un point de terminaison / api / webserver.

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

J'avais affaire au même problème et je pensais que c'était une erreur de conf mais non. Je copiais le fichier conf dans le /etc/nginx/conf.d/dossier. Cela fonctionne en dev, mais dans la version de construction, cela cause ce problème. Lorsque la route échoue, nginx ne se replie pas sur l'index.

Copiez simplement le fichier conf dans le bon dossier: /etc/nginx/conf.d/default.conf

Exemple d'instruction Dockerfile: COPY .docker/prod/nginx.conf /etc/nginx/conf.d/default.conf

J'espère que ça aide.

diogopalhais
la source
-1
location / {
    root /path/to/root/directory/of/staticfiles;
    index index.html;
    try_files $uri /index.html;
}
Sagarpatidar
la source
Les réponses au code uniquement sont déconseillées sur Stack Overflow car elles n'expliquent pas comment cela résout le problème. Veuillez modifier votre réponse pour expliquer ce que fait ce code et comment il améliore les réponses existantes, afin qu'il soit utile au PO ainsi qu'aux autres utilisateurs ayant des problèmes similaires.
FluffyKitten