David Massey
David Massey

Reputation: 319

React router doesn't route traffic when hosted on firebase

So this is pretty much just the product of creat-react-app and firbase init. It works exactly as expected when I do npm start but when I upload the package to firebase, the only page I am able to hit is at the / path. Even if I switch the components, they one on the / path will be hit.

App.js file

import React, { Component } from 'react';
import './App.css';
import Ok from './Ok';
import {Route, Switch} from 'react-router-dom';
import Home from "./Home";

class App extends Component {
  render() {
    return (
            <main>
                <Switch>
                    <Route exact={true} path="/" component={Home}/>
                    <Route path="/ok" component={Ok}/>
                </Switch>
            </main>
    );
  }
}

export default App;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {BrowserRouter} from "react-router-dom";

ReactDOM.render((
    <BrowserRouter>
        <App />
    </BrowserRouter>), document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();

firebase.json

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

Directory structure

.
├── build
│   ├── asset-manifest.json
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   ├── precache-manifest.ecdffa8fba4446ec939aeb81deef8a46.js
│   ├── service-worker.js
│   └── static
│       ├── css
│       │   ├── main.62e37b1d.chunk.css
│       │   └── main.62e37b1d.chunk.css.map
│       ├── js
│       │   ├── 1.c86c31d4.chunk.js
│       │   ├── 1.c86c31d4.chunk.js.map
│       │   ├── main.68e18920.chunk.js
│       │   ├── main.68e18920.chunk.js.map
│       │   ├── runtime~main.229c360f.js
│       │   └── runtime~main.229c360f.js.map
│       └── media
│           └── logo.5d5d9eef.svg
├── firebase.json
├── package.json
├── package-lock.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
├── README.md
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── Home.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── Ok.js
    └── serviceWorker.js

ANSWER:

I removed the main tag from App.js and moved the BrowserRouter from index.js to App.js, wrapping the Switch tag with it

Upvotes: 14

Views: 5910

Answers (2)

eGangotri Foundation
eGangotri Foundation

Reputation: 11

by only modifying my firebase.json to include

"rewrites": [
    {
        "source": "**",
        "destination": "/index.html"
    }
]

my firebase hosted site shows routes properly.

Upvotes: 1

Alexander Staroselsky
Alexander Staroselsky

Reputation: 38827

You need to make sure the rewrites are enabled in your Firebase hosting configuration to redirect all requests to your index.html file. This assumes you are using create-react-app:

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
    ]
  }
}

The init command for Firebase actually provides this is an option when creating a project.

You will need to redeploy firebase deploy to propagate the changes.

Update: With the aforementioned firebase.json hosting configuration the following index.js and App.js, I was able to successfully deploy a create-react-app with working react-router-dom routing using npm run build following by firebase deploy.

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
serviceWorker.unregister();

App:

import React, { Component } from 'react';
import { Route, Link, Switch } from "react-router-dom";
import './App.css';

const Home = () => <h1>Home</h1>;
const Ok = () => <h1>Ok</h1>;

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/ok">Ok</Link></li>
          </ul>
        </header>
        <main>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route path="/ok" component={Ok} />
          </Switch>
        </main>
      </div>
    );
  }
}

export default App;

Hopefully that helps!

Upvotes: 20

Related Questions