Reputation: 518
I have boilerplate-like single-page application with wouter
-based routing - application is functional in local environment. Goal I'm trying to archive is deployment of mentioned application to vercel
, yet there is a problem in application routing - things are ok when I run application locally but it returns Not Found (404) errors when it's deployed to cloud.
Deployment has no problem when it's run through procfile
, Docker Container or "bare-metal" - but one it touches Vercel's Edge application do not care about routing at all.
I have tried multiple routing libraries (wouter
, react-router
) and problem still existed and behaved without any difference.
Implementation of routing is correct, and path rewrites which are required and recommended by Vercel are configured in vercel.json
and are provided below.
{
"github": {
"silent": true
},
"rewrites": [
{
"source": "(.*)",
"destination": "/index.html"
}
]
}
Commonly proposed solution for similar Vercel-related problems was following configuration yet this still do not change outcome at all.
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
}
My file structure is following, as my project is mono-repository managed by turbo
.
.
├── apps/
│ └── web/
│ ├── src
│ └── package.json
└── vercel.json
Upvotes: 8
Views: 12503
Reputation: 518
TL;DR
For monorepository configurations vercel.json
should be contained under $ROOT/$PROJECT/vercel.json
instead $ROOT/vercel.json
.
$ROOT/$PROJECT/vercel.json
{
"github": {
"silent": true
},
"rewrites": [
{
"source": "(.*)",
"destination": "/index.html"
}
]
}
Configuration in vercel.json
was correct at the time it was added to question, the issue was not present in project configurations that were single-package repositories with vercel.json
at Root Directory along package.json
. Yet with monorepository approach same configuration had different behaviour than expected (as one in single-package repository) - solution for such problem was moving vercel.json
into Project Directory of repository where package.json
was contained (the one which indicates workspace, instead one which indicates given React.js project).
Upvotes: 0
Reputation: 180
TLDR
Add an empty 404.html in the public folder (you can put the title in the title tag) with this script in the head section
<script type="text/javascript">
var pathSegmentsToKeep = 0;
var l = window.location;
l.replace(
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
l.pathname.split('/').slice(0, 1 + pathSegmentsToKeep).join('/') + '/?/' +
l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash
);
</script>
Then add this script to your index.html
<script type="text/javascript">
(function(l) {
if (l.search[1] === '/' ) {
var decoded = l.search.slice(1).split('&').map(function(s) {
return s.replace(/~and~/g, '&')
}).join('?');
window.history.replaceState(null, null,
l.pathname.slice(0, -1) + decoded + l.hash
);
}
}(window.location))
</script>
This worked perfectly for me after deploying my app to render.com
To handle the "real" not found response, you can add this route
<Route path="*" element={<p>Page not found</p>} />
For more information you can visit this repo spa-github-pages
Credits to @rafgraph
Upvotes: 1
Reputation: 396
You can a create simple rewrites rules in the serve. In my case I use Vercel. Then you can find something similar this.
Create in the project root a file vercel.json
And writer
{
"rewrites": [{ "source": "/(.*)", "destination": "/" }]
}
P.S.: Don't forget to enable rewrites in vercel.
Upvotes: 18