React-router e nginx

107

Estou fazendo a transição do meu app react de webpack-dev-server para nginx.

Quando vou para o url raiz "localhost: 8080 / login", simplesmente obtenho um 404 e, no log do nginx, vejo que ele está tentando obter:

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

Onde devo procurar uma solução?

O bit do meu roteador em reação fica assim:

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

E meu arquivo nginx assim:

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


    }
}

EDITAR:

Eu sei que a maior parte da configuração funciona porque quando vou para localhost: 8080 sem estar logado, também obtenho a página de login. isso não é através de um redirecionamento para localhost: 8080 / login - é algum código de reação.

Martin
fonte
1
Os parâmetros para try_filesdevem ser URIs e não nomes de caminho. Experimente:try_files $uri $uri/ /index.html;
Richard Smith
@RichardSmith OK ... eu vi isso como o nome do caminho para o arquivo index.html. Tentei mudar para o que você sugeriu - mas obtive o mesmo resultado. ## / wwwroot / login "falhou (2: arquivo ou diretório inexistente) ## você tem outras sugestões. Vou mergulhar nisso esta noite ...
martin
@martin você já conseguiu resolver isso? Estamos vendo a mesma coisa, mas já tinha a linha try_files lá.
Billy Ferguson

Respostas:

241

O bloco de localização na configuração do nginx deve ser:

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

O problema é que as solicitações para o arquivo index.html funcionam, mas você não está dizendo ao nginx para encaminhar outras solicitações para o arquivo index.html também.

Toby
fonte
8
Verifique isso para configurações mais avançadas (cache, 404 para arquivos .js, .css ausentes, etc.) gkedge.gitbooks.io/react-router-in-the-real/content/nginx.html
Gianfranco P.
Parece que o React Router não deve causar uma viagem de ida e volta ao servidor ... isso pode ser bloqueado localmente?
Scotty H
se o nginx não rotear a solicitação para o arquivo index.html, o JS dentro do React Router nem mesmo saberá da solicitação. Essa resposta roteia todas as solicitações para o React, permitindo que o React Router trate todas as solicitações.
Toby de
Também é importante usar a configuração da página inicial padrão em package.json, que usa a raiz do servidor. Eu tinha definido como '.', (Use caminhos relativos), mas então o nginx tentou servir /custompath/static/main.js, que obviamente irá falhar, resultando em um site que não funciona.
boerre
apenas avisando, certifique-se de que a configuração está realmente sendo carregada, a minha estava em conflito com o padrão e apenas sendo ignorada. suspiro
4c74356b41
18

Aqui estão minhas soluções

tentativa simples:

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

não tente mais por tipos não-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;
}

não tente mais tipos e diretórios não-html (tornando-os try_filescompatíveis com indexe / 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
fonte
9

Talvez este não seja o caso exato aqui, mas para qualquer pessoa que esteja executando um dockercontêiner para seu reactprojeto com react-routere webpack-dev-server, no meu caso, eu tinha tudo o que precisava em meu 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;
    }
  }

Mesmo assim, o nginx não enviaria erros 404 para a raiz /. Depois de examinar o contêiner, percebi que há alguns configs /etc/nginx/conf.d/default.confque, de alguma forma, sobrescrevem meus configs, portanto, excluir esse arquivo no meu dockerfileresolveu o problema:

...
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
fonte
1
Você salvou meu dia!
Bilal Hussain
4

Aqui está a solução que funciona para mim no servidor ao vivo:

Acabei de seguir este tutorial e com a configuração básica do Nginx simplesmente configurei o bloco de localização.

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

Para mim, nada funcionou até eu adicionar uma diretiva root. Isso funcionou para mim também usando um proxy reverso para acessar um endpoint / api / webserver.

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

Eu estava lidando com o mesmo problema e pensei que era um erro de conf, mas não. Eu estava copiando o arquivo conf para a /etc/nginx/conf.d/pasta. Isso funciona no dev, mas na versão build causa esse problema. Quando a rota falha, o nginx não retorna ao índice.

Basta copiar o arquivo conf para a pasta certa: /etc/nginx/conf.d/default.conf

Exemplo de instrução Dockerfile: COPY .docker/prod/nginx.conf /etc/nginx/conf.d/default.conf

Espero que ajude.

diogopalhais
fonte
-1
location / {
    root /path/to/root/directory/of/staticfiles;
    index index.html;
    try_files $uri /index.html;
}
sagarpatidar
fonte
Respostas apenas de código são desencorajadas no Stack Overflow porque não explicam como ele resolve o problema. Edite sua resposta para explicar o que este código faz e como ele melhora as respostas votadas existentes, de modo que seja útil para o OP e também para outros usuários com problemas semelhantes.
FluffyKitten