Search code examples
reactjssingle-page-applicationgithub-pagesvite

page not found - react/vite app not routing correctly on github pages


I deployed my app to gh-pages and the root works, but whenever I reroute or try and add to the root, I get a page not found error. Locally it works.

I've seen people suggest changing from <BrowserRouter> to <HashRouter> but that didn't help. I've also seen, and even used, a solution for create-react-app or webpack where you add some code to the index.html file in the public directory as well as a 404.html but the issue is vite has a different file structure.

Where would I put them in a vite application where there's nothing in the public directory. It does have a dist folder with an index.html but I'm not sure if that's the one.

Not sure what code I would need to show, but here's my main.jsx and App.jsx files:

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <Header />
      <div className="app">
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/example" element={<Example />} />
        </Routes>
      </div>
    </Router>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

Again, locally this works, and when deploying to gh-pages the root or home page work, but no extended routes. Like I said, I had a similar issue with webpack but the solution I got there didn't work since vite has different file structure so I was unsure how to add the correct files.

EDIT: I've also seen a github issue where a user had a similar issue and the solution was to define routes in the vite.config.js but again the difference there is that user had multiple index.html files for each component/route. I just have the standard <BrowserRouter> situation wrapping my routes.


Solution

  • adding a 404.html in the public folder:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Page Not Found</title>
        <script>
          sessionStorage.redirect = location.href;
        </script>
        <meta http-equiv="refresh" content="0;URL='/'" />
      </head>
      <body></body>
    </html>
    

    This JS in the root's index.html just before the closing </body> tag:

        <script>
          (() => {
            const redirect = sessionStorage.redirect;
            delete sessionStorage.redirect;
            if (redirect && redirect !== location.href) {
              history.replaceState(null, null, redirect);
            }
          })();
        </script>
    

    And lastly reconfiguring the vite.config.js file:

    export default defineConfig({
      plugins: [react()],
      build: {
        rollupOptions: {
          input: {
            main: resolve(__dirname, "index.html"),
            404: resolve(__dirname, "public/404.html"),
          },
        },
      },
    });