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.
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"),
},
},
},
});
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With