web-dev-qa-db-fra.com

React Le routage fonctionne sur la machine locale mais pas Heroku

React/react router/heroku question here (c'est probablement heroku où il échoue).

Je suis ce merveilleux tutoriel: https://medium.com/@patriciolpezjuri/using-create-react-app-with-react-router-express-js-8fa658bf892d#.y77yjte2j et tout fonctionne jusqu'au point où je le poste sur heroku et j'essaie de naviguer vers https://appname.herokuapp.com/about et j'obtiens une erreur 404 Not Found/nginx. Bien sûr, selon le tutoriel, il est censé afficher une page À propos.

Conclusion: le routeur React ne fonctionne pas sur Heroku et je ne peux pas comprendre pourquoi .

J'ai essayé de modifier mon server/app.js fichier comme suggéré dans ceci: les routes React ne fonctionnent pas dans la build create-react-app de Facebook

// server/app.js
const express = require('express');
const morgan = require('morgan');
const path = require('path');

const app = express();

console.log('hi from /src/server.js')
// Setup logger
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] :response-time ms'));

// Serve static assets
app.use(express.static(path.resolve(__dirname, '..', 'build')));

// Always return the main index.html, so react-router render the route in the client

app.get('/about', (req, res) => {

  console.log('hi from app.get.about')
  console.log(req)
  console.log(res)
  res.sendFile(path.resolve(__dirname, '..', 'build', 'index.html'));
});
app.get('/*', (req, res) => {

  console.log('hi from app.get')
  console.log(req)
  console.log(res)
  res.sendFile(path.resolve(__dirname, '..', 'build', 'index.html'));
});


module.exports = app;

mais cela ne fonctionne pas et ne consigne rien du tout dans la console:

2017-01-20T21:03:47.438140+00:00 heroku[web.1]: Starting process with command `bin/boot`
2017-01-20T21:03:49.540005+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/main.242e967b.js (from .profile.d/inject_react_app_env.sh)
2017-01-20T21:03:49.695317+00:00 app[web.1]: Starting log redirection...
2017-01-20T21:03:49.695899+00:00 app[web.1]: Starting nginx...
2017-01-20T21:03:51.108255+00:00 heroku[web.1]: State changed from starting to up
2017-01-20T21:04:22.720627+00:00 heroku[router]: at=info method=GET path="/" Host=sentieoapp1.herokuapp.com request_id=fb8bc13b-f6b5-47bc-8330-443f28e211df fwd="132.147.73.97" dyno=web.1 connect=0ms service=3ms status=200 bytes=627
2017-01-20T21:04:22.746761+00:00 app[web.1]: 10.158.165.5 - - [20/Jan/2017:21:04:22 +0000] "GET / HTTP/1.1" 200 386 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
2017-01-20T21:04:23.076521+00:00 app[web.1]: 10.158.165.5 - - [20/Jan/2017:21:04:23 +0000] "GET /static/js/main.242e967b.js HTTP/1.1" 200 62263 "https://sentieoapp1.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
2017-01-20T21:04:23.056416+00:00 heroku[router]: at=info method=GET path="/static/js/main.242e967b.js" Host=sentieoapp1.herokuapp.com request_id=436d5ce5-ee39-4ab7-9e12-f5871e0fd552 fwd="132.147.73.97" dyno=web.1 connect=0ms service=25ms status=200 bytes=62540
2017-01-20T21:04:23.745285+00:00 heroku[router]: at=info method=GET path="/static/css/main.9a0fe4f1.css" Host=sentieoapp1.herokuapp.com request_id=80438aaa-58c4-456e-8df9-7a29e49bc4ba fwd="132.147.73.97" dyno=web.1 connect=0ms service=2ms status=200 bytes=560
2017-01-20T21:04:23.766676+00:00 app[web.1]: 10.158.165.5 - - [20/Jan/2017:21:04:23 +0000] "GET /static/css/main.9a0fe4f1.css HTTP/1.1" 200 301 "https://sentieoapp1.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
2017-01-20T21:04:24.044940+00:00 heroku[router]: at=info method=GET path="/static/media/logo.5d5d9eef.svg" Host=sentieoapp1.herokuapp.com request_id=bcbc1906-3b90-4f13-a700-f432f79c725d fwd="132.147.73.97" dyno=web.1 connect=0ms service=1ms status=200 bytes=2902
2017-01-20T21:04:24.065013+00:00 app[web.1]: 10.158.165.5 - - [20/Jan/2017:21:04:24 +0000] "GET /static/media/logo.5d5d9eef.svg HTTP/1.1" 200 2671 "https://sentieoapp1.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
2017-01-20T21:04:26.264631+00:00 heroku[router]: at=info method=GET path="/about" Host=sentieoapp1.herokuapp.com request_id=0caef324-9268-4ebb-a3f5-0fb047100893 fwd="132.147.73.97" dyno=web.1 connect=0ms service=4ms status=404 bytes=403
2017-01-20T21:04:26.284717+00:00 app[web.1]: 10.158.165.5 - - [20/Jan/2017:21:04:26 +0000] "GET /about HTTP/1.1" 404 191 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"

et c'est là que je suis coincé. Je connais Express et l'ai déjà fait fonctionner sur Heroku, mais c'est un tout autre niveau de cauchemar. Je comprends que ce n'est pas du routage côté serveur, mais plutôt que je fais du routage à partir d'une seule page index.html. Mais si je peux le faire fonctionner sur ma machine locale, pourquoi ne fonctionne-t-il pas sur Heroku?

27
swyx

En fait, je suis tombé sur ce post avant 3 heures de recherche dans Reactor-Routeur et la documentation Heroku. Pour swyx et toute autre personne ayant le même problème, je vais décrire le minimum de ce que vous devez faire pour que cela fonctionne.

router.jsModifiez évidemment AppSplash et AppDemo à vos composants)

export default <Router history={hashHistory}>
  <Route path="/" component={App}>
    <IndexRoute component={AppSplash}/>
    <Route path="demo" component={AppDemo}/>
  </Route>
</Router>

--- (app.js

import React, { Component } from 'react'

class App extends Component {
static propTypes = {
  children: PropTypes.node
}

render() {
  const { children } = this.props
  return (
    <div>
      {children}
    </div>
  )
}
}

export default App

Créez un nouveau fichier à la racine de votre répertoire personnel et nommez-le static.json. Mettez ça dedans.

{
  "root": "build/",
  "clean_urls": false,
  "routes": {
    "/**": "index.html"
  }
}

Poussez à nouveau vers Heroku. Les itinéraires devraient fonctionner cette fois.

Explication:

Vous devez modifier le webpack par défaut de Heroku, sinon le service se confond avec la façon de gérer le routage côté client. Essentiellement ce que fait static.json. Le reste est juste la bonne façon de gérer le routage selon la documentation 'react-router'.

38
HarshMarshmallow

Comment corriger les erreurs de routage côté client (erreurs Heroku 404):

React Browser Router

Si vous utilisez React Browser Router , en tant que module npm avec create-react-app, alors la solution (qui fonctionne pour moi) consiste à créer un static.json fichier (dans le même répertoire que package.json).

{
  "root": "build/",
  "clean_urls": false,
  "routes": {
    "/**": "index.html"
  }
}

Voici pourquoi cette solution fonctionne:

Create-react-app est pour la plupart un serveur Node.Js qui sert côté client React. Le répertoire statique public est mappé au / endpoint, et la visite de ce point de terminaison à partir d'un navigateur téléchargera le index.html page Web. Cette page Web charge à son tour le composant React. Et parce que React Browser Router est un composant React, les itinéraires sont chargés dynamiquement après avoir visité le / point final. En d'autres termes, avant le index.html la page Web est chargée tous nos React Browser Router itinéraires entraîneront 404 erreurs sur Heroku. Pour résoudre ce problème, un static.json le fichier peut être utilisé pour mapper tous les points de terminaison avec le modèle suivant /** au index.html fichier, qui à son tour chargera React Browser Router et chargera correctement les composants react pour cette route.

À partir d'un serveur HTTP Apache:

De même, sur un serveur HTTP Apache créant un .htaccess fichier dans le répertoire public, remappera tous les points de terminaison qui correspondent à /** au index.html fichier.

Options -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [QSA,L]

Plus de ressources

Lisez également la section "Déploiement" du create-react-app README, qui contient une tonne de bonnes informations sur la façon de reconfigurer le serveur pour utiliser le routage côté client.

https://facebook.github.io/create-react-app/docs/deployment

Routeur statique React

Enfin, React Router propose un routeur statique, React Static Router , qui peut être utilisé avec le "react-dom/server" npm module sur un serveur Node.js, pour rendre [~ # ~] jsx [~ # ~] côté serveur, et n'a pas besoin de static.json ou .htaccess reconfiguration.

26
tfmontague

Essaye ça:

app.get("*", (req, res) => {
  let url = path.join(__dirname, '../client/build', 'index.html');
  if (!url.startsWith('/app/')) // since we're on local windows
    url = url.substring(1);
  res.sendFile(url);
});

A fonctionné pour moi quand j'ai mis dans server.js.

1
David Hahn