2

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.

Yehuda
  • 27
  • 15
  • Does this answer your question? [React-Router issue when deployed to Github Pages?](https://stackoverflow.com/questions/71290365/react-router-issue-when-deployed-to-github-pages) – Moshe Katz Apr 27 '23 at 14:39

2 Answers2

1

The main point here is to understand how GH pages serve static files. If there is not a file matched to a given URL, it automatically serves 404.html. So we just need to have 404.html, which has the same content as the index.html that we get from vite build.

Therefore, all you need to to is to copy index.html to 404.html inside dist directory.

I'm not sure how you manage GH page publish.

  • If you use Github Actions, please add a custom step to copy index.html to 404.html.

    cp ./dist/index.html ./dist/404.html
    
  • If you use gh-pages branch, I think you should copy index.html to 404.html before you push your changes to the branch.

I have created a public repo, which you can take a look for a reference. https://github.com/richard929/vite-gh-pages-example

I used react-router v6, and github actions for GH pages publish. I hope you already know about base configuration of vite, when deploying Vite app to static website.

Richard Zhan
  • 460
  • 3
  • 10
  • When deploying `gh-pages` it runs `npm run build` which creates a new dist folder. How can I keep this file in the folder during production – Yehuda May 01 '23 at 17:17
  • I think it depends on the way deploying to production. If you use pipelines, you can always extend it to add custom step. If you do this manually, then no trouble, I suppose. – Richard Zhan May 02 '23 at 01:57
1

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"),
      },
    },
  },
});
Yehuda
  • 27
  • 15