16

My app works fine in webpack development server. Now, I want to deploy it to my production server. So I built bundle.js. I tried serving the file on express server, but I can't access urls other than the root /.

For example, here is my react routes:

var Routes = () => (
    <Router history={browserHistory}>
        <Route path="/" component={Landing}>
        </Route>
        <Route path="/app" component={App}>
        </Route>
    </Router>
)

and express app (I put bundle.js and index.html in ./public):

app.use(express.static('./public'));
app.listen(port, function () {
    console.log('Server running on port ' + port);
});

Landing page http://localhost:3000/ works. But the app http://localhost:3000/app doesn't. Instead, I got an error Cannot GET /app.

Komsit Prakobphol
  • 173
  • 1
  • 1
  • 8

1 Answers1

15

You need to declare a "catch all" route on your express server that captures all page requests and directs them to the client. First, make sure you're including the path module on your server:

var path = require('path');

Then, put this before app.listen:

app.get('*', function(req, res) {
  res.sendFile(path.resolve(__dirname, 'public/index.html'));
});

This assumes you're inserting bundle.js into index.html via a script tag.

Rick Runyon
  • 4,204
  • 1
  • 17
  • 15
  • Thanks, works perfectly! Found one minor typo in your solution: It should be res.sendFile(path.resolve(__dirname`,` 'public/index.html')); – Komsit Prakobphol Mar 10 '16 at 23:29
  • Great! Also thank you for noticing that, I've edited the answer. – Rick Runyon Mar 11 '16 at 02:05
  • but what if my webpack output to './dist/bundle.js', while my unbundled code and index.html are in './public' ? what I need to do in prod? my express server serve static files from 'public' .. but the index.html reference script to 'dist/bundle.js' - CANNOT REACH IT ....(this is works fine with webpack's dev server) – Refactor-Man May 18 '16 at 14:49
  • 1
    That's the same setup I have. You just need to copy ./dist/bundle.js to ./public (make sure the path for bundle.js match relative path defined in index.html - should be ./public/dist/bundle.js in your case). You need to remember to do it in every release. I think you can automate this with a script, webpack plugin or gulp task – Komsit Prakobphol May 20 '16 at 01:19
  • 2
    Followed this method and when ever a Get request is done it returns the html file as reponse – TRomesh Dec 27 '16 at 00:56
  • make sure this is put as the last route in case there are api routes, which would otherwise be over-ridden. – Joe Jan 06 '17 at 16:21
  • @TRomesh I'm also getting the html file as response for js or css files. Did you resolve your issue (which I'm guessing is also mine)? – tscizzle Mar 24 '17 at 22:28
  • 2
    @tscizzle yeah i got it fixed by changing the order of some lines just app.get('*', function(req, res) { res.sendFile(path.resolve(__dirname, 'public/index.html')); }); at the end, before other routes and server.listen(port); – TRomesh Mar 31 '17 at 16:30