react-router does not work in production and surge deployments

32,821

Solution 1

This is happening because users aren't being served the index.html which bootstraps your app when they visit those URLs directly.

For surge, you can add a 200.html file which contains the same contents as the index.html you're deploying (or just rename it to 200.html) - this will then be served to users at any URL they visit which doesn't correspond to a static file, allowing your app to start running.


Edit: looks like you're using create-react-app. This works when you're developing locally because create-react-app's react-scripts package handles serving your index.html as a fallback for these requests.

The react-scripts user guide has sections on how to handle this when deploying to GitHub Pages and surge.sh (as above).

Solution 2

Changing .htaccess file in the case of using apache as the web server in your build folder worked for me:

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

Solution 3

This issue happens on all single page applications (e.g. react, angular). Follow below steps to resolve (only 4 surge):

  1. npm run build
  2. cd build
  3. cp index.html 200.html
  4. surge

Solution 4

When deploying the build on static servers, in our React App if we would have used routers that use the HTML5 pushState history API under the hood (for example, React Router with browserHistory), the static file servers might fail to load the routes and appropriate screens and show up 404 - Not Found error.

As described in the create-react-app Deployment article:

when there is a fresh page load for a path for ex: /todos/42, the server looks for the file build/todos/42 and does not find it. The server needs to be configured to respond to a request to /todos/42 by serving index.html

So to make the routes working when using Node with Express, one can add configure the server index.js as below:

const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));

// PATH CONFIGURATION TO RESPOND TO A REQUEST TO STATIC ROUTE REQUEST BY SERVING index.html
app.get('/*', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(5000);
console.log('Server is listening on http://localhost:5000');

If you’re using Apache HTTP Server, you need to create a .htaccess file in the public folder of your React APP that looks like this:

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

It will get copied to the build folder when you run npm run build.

Solution 5

I had the same problem. And i solved it very easily... :)

I used react at my front-end(Create-React-App) and an express backend. In dev mode all things works great but when i switched to the production build there was some routing issues in my react routing. After a long survey i found that the problem is on the server side serving up the index.html file.

It should be after all the server side routing but before all the app.post handler. In other words the following line should be placed after all app.gets and before all app.posts

// PRODUCTION
App.get('*', (req, res)=>{
res.sendFile(path.resolve(where, the, index.html, is))
})
Share:
32,821

Related videos on Youtube

isuruAb
Author by

isuruAb

BY DAY: Blogger, Designer, Freelancer Web Developer By NIGHT: FOSS Contributor and volunteer developer for non-profitable organizations find me in an any network by #isuruab or #isuruAb

Updated on May 03, 2021

Comments

  • isuruAb
    isuruAb about 3 years

    My react application is working fine on localhost but when after i deployed it in gh-pages or surge it does not give me to move among pages using URL.

    • This is the project repo link
    • Demo url here

    users can go to signup page by clicking menuItem of top right corner. but If user use http://chat.susi.ai/signup/ URL, it gives 404 page

    I tried several solutions from internet but didn't work.

    Next question is : I created a 404 page to show up when user tries to move to broken links.It works fine in localhost. but not in production. I tried this solution but nothing changed.

    this is part of my index.js file

    const App = () => (
        <Router history={hashHistory}>
            <MuiThemeProvider>
                <Switch>
                    <Route exact path="/" component={ChatApp} />
                    <Route exact path="/signup" component={SignUp} />
                    <Route exact path="/logout" component={Logout} />
                    <Route exact path="/forgotpwd" component={ForgotPassword} />
                    <Route exact path="*" component={NotFound} />
    
                </Switch>
            </MuiThemeProvider>
        </Router>
    );
    
    ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
    

    If someone can suggest good solution with sample code for my problems that would be really helpful for me.

  • Carl Bosch
    Carl Bosch over 5 years
    indeed, serving the index.html file when visiting the subpath works fine :-)
  • Nisuga Jayawardana
    Nisuga Jayawardana over 4 years
  • Isaac Pak
    Isaac Pak about 4 years
    This answer doesn't work for me, but @NisugaJayawardana link did.
  • Mukul Kumar Jha
    Mukul Kumar Jha over 3 years
    HI @Rahul gupta, I'm using nginx server, where should I add similar fixes?
  • Nate Wessel
    Nate Wessel over 3 years
  • Kyle Pennell
    Kyle Pennell about 3 years
    do we put the .htaccess file in the build folder?
  • Shubham Kumar
    Shubham Kumar almost 3 years
    Yes. add the .htaccess where your index.html resides
  • MindRoasterMir
    MindRoasterMir almost 2 years
    it does not work for me for angular.
  • Anas
    Anas almost 2 years
    what the step 4 surge do? I got bash: surge: command not found