How to serve production react bundle.js built by webpack?
Asked Answered
N

1

17

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.

Nonsuch answered 10/3, 2016 at 22:38 Comment(0)
B
16

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.

Bootlick answered 10/3, 2016 at 22:59 Comment(8)
Thanks, works perfectly! Found one minor typo in your solution: It should be res.sendFile(path.resolve(__dirname, 'public/index.html'));Nonsuch
Great! Also thank you for noticing that, I've edited the answer.Bootlick
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)Courage
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 taskNonsuch
Followed this method and when ever a Get request is done it returns the html file as reponseBusinessman
make sure this is put as the last route in case there are api routes, which would otherwise be over-ridden.Mungo
@Businessman 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)?Gelatinoid
@Gelatinoid 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);Businessman

© 2022 - 2024 — McMap. All rights reserved.