React.js (Vite) application returns 404 on return in monorepository
Asked Answered
I

3

8

I have a simple React.js application with wouter-based routing and Vercel deployments that drive me into a little issue where I have no idea about the solution. It always returns 404 after refresh (of subpage). It's worthly to notice my configuration of repository includes turbo and few applications (server and web).

My code looks a bit like this.

    <>
        <Route path='/' component={Intro} />
        <Route path='/dashboard' component={Dashboard} />
    </>

Where on <Intro /> I have <Link /> to /dashboard which should transfer me to <Dashboard /> page. And it does work on my local machine, in a container, and on Linux-based deployment, but it doesn't really work in vercel deployment, even if I tried to resolve this issue with the configuration of repository/vercel.json.

{
    "github": {
        "silent": true
    },
    "rewrites": [
        {
            "source": "(.*)",
            "destination": "/index.html"
        }
    ]
}

Also tried an alternative version of rewrites and still the same issue.

{
  "rewrites": [{ "source": "/(.*)", "destination": "/" }]
}

NOTE: I was also trying to use react-router but the same problem exists. Same problem exist when application is hosted on netlify but doesn't exist at all when hosted on heroku or run inside docker container.

Interknit answered 26/1, 2022 at 21:52 Comment(2)
#69702243 The solution has ben soved in this Question!Dedifferentiation
Not exactly, I was not aware of that vercel can have a problems with monorepo structure. Question you provided is on completely different topic.Interknit
I
0

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).

Interknit answered 21/7, 2024 at 7:27 Comment(0)
D
16

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.

Dedifferentiation answered 11/3, 2022 at 3:31 Comment(3)
Mate you're wrong, You cannot put vercel.json in Project Root, because if you're using monorepo structure this will not work. It's supposed to be in Application Directory (with package.json).Interknit
yea as @Interknit said, I put vercel.json in my application directory (mine is called /client) and it worked :)Itin
Sorry! I meant. Exactly next to the package.json.Dedifferentiation
C
1

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

Compensation answered 6/12, 2022 at 0:2 Comment(0)
I
0

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).

Interknit answered 21/7, 2024 at 7:27 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.