La aplicación Node (Express) / React solo funciona localmente

Esquema de la cuestión

Tengo una aplicación Node / React simple, que funciona bien usando heroku local .

El backend de Node tiene un punto final /api/users , que devuelve algunos JSON codificados.

Después de heroku local , visitar localhost:5000/users funciona como se esperaba, mostrando los usuarios codificados según el componente React de Users.js .

Sin embargo, cuando se empuja a Heroku, solo funciona la página / raíz. Ir a /users muestra Not Found , y ir a /api/users devuelve el JSON.

No estoy seguro de por qué funciona localmente y no en Heroku, se agradece cualquier ayuda.

Código

Rutas exprés:

 var express = require('express'); var router = express.Router(); var path = require('path'); router.get('/api/users', function(req, res, next) { res.json([{id: 1, name: 'Colin'}, {id: 2, name: 'Spodie'}]) }); module.exports = router; 

El archivo expreso app.js:

 var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var cors = require('cors'); var config = require('./config/dev') var index = require('./routes/index'); var app = express(); app.use(cors()) app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); // serve static files from React app.use(express.static(path.join(__dirname, '../frontend/build'))); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); }); module.exports = app; 

React App.js archivo:

 import React, { Component } from 'react'; import { Switch, Route } from 'react-router-dom'; import Users from './Users'; import NotFound from './NotFound'; import Home from './Home'; class App extends Component { state = {users : []} render() { return ( 
); } } export default App;

Reactiva el archivo api.js:

 const api = process.env.BACKEND_URL || 'http://localhost:5000' export const getUsers = () => ( fetch(`${api}/api/users`) .then(res => res.json()) ) 

Reaccionar package.json

 { "name": "frontend", "version": "0.1.0", "private": true, "dependencies": { "react": "^15.6.1", "react-dom": "^15.6.1", "react-router-dom": "^4.2.2", "react-scripts": "1.0.12" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "proxy": "http://localhost:5000" } 

Capturas de pantalla

Página de inicio corriendo localmente página de inicio corriendo localmente

Página de inicio que se ejecuta en Heroku página de inicio que se ejecuta en heroku

Página de usuarios corriendo localmente página de usuarios corriendo localmente

Página de usuarios corriendo en Heroku Página de usuarios corriendo en heroku

Está sirviendo archivos estáticos, pero también necesita reenviar todas las solicitudes HTTP GET al enrutador de reacción del lado del cliente para que pueda manejarlas. Es posible que desee poner esta ruta a su app.js :

 app.get("*", function (req, res) { res.sendFile(__dirname + "/path/to/index.html") })