Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 515
David Massey Avatar asked Oct 23 '18 00:10

David Massey


1 Answers

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!

like image 150
Alexander Staroselsky Avatar answered Oct 25 '22 23:10

Alexander Staroselsky