Create-React-App in production: Routes not found

2019-07-28 12:17发布

问题:

I have a fullstack app with Create-React-App and Express.js as the backend.

The development setup (CRA running on port 3000) is realized by CRA's proxies so I can forward certain routes directly to the backend (running on port 5000):

"proxy": {
    "/auth/*": {
      "target": "http://localhost:5000"
    },
    "/api/*": {
      "target": "http://localhost:5000"
    }
}

For logging out a user I have a corresponding route:

app.get('/api/logout', (req, res) => {
    req.logout();
    res.redirect('/');
});

And a logout button that points to this route:

<a key="logout" href="/api/logout">Logout</a>

In development mode, running :3000 and :5000, everything works perfectly. Clicking on on the button sets the URL in the browser which calls the route, the proxy forwards and the backend recognizes and handles the request properly => Session killed!

In production mode, hosted on Heroku, the route is simply not found and not triggered. In the network tab the server serves the static html file, maybe due to this configuration:

if (process.env.NODE_ENV === 'production') {

    app.use(express.static('client/build'));

    const path = require('path');
    app.get('*', (req, res) => {
        res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
    });
}

If I logout the user programmatically, by calling the same route onClick, it works:

await axios.get('/api/logout');

But why is the simple redirect of the browser with the <a> not working in production?

THX!

回答1:

Change

if (process.env.NODE_ENV === 'production') {

app.use(express.static('client/build'));

const path = require('path');
app.get('*', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}

To this:

let root = path.join(__dirname, 'client', 'build');
app.use(express.static(root));
app.use(function(req, res, next) {
if (req.method === 'GET' && req.accepts('html') && !req.is('json') && 
  !req.path.includes('.')) {
     res.sendFile('index.html', { root });
  } else next();
});

Maybe this helps: Configure production environment in a create-react-app