https://github.com/gatsbyjs/gatsby/issues/5312
The problem is we do redirects in production on navigation but we don't check if we should redirect during the initial render e.g. from a SW.
is this what's causing my redirected url to show the 404 page for a sec or two before redirecting to the new url?
very possibly
any way to fix it?
My initial comment has a hint at the direction for a fix — would you like to dive in and explore the problem and make a PR?
@KyleAMathews How can I reproduce this and I will explore the problem?
@KyleAMathews is that not what the maybeRedirect(window.location.pathname)
call is doing on line 44? Checking for an initial redirect?
I may be experiencing an issue linked to this. I’m using react-router-dom
’s Redirect
to redirect from /
to /${locale}/
in root of the site. It redirects fine to the proper route, the route displays 404 until manually refreshed. Here’s how it feels: http://trafficdesignpl.netlify.com/
Here’s what I’m doing there:
import { Redirect } from "react-router-dom";
import locale from "browser-locale";
import React, { PureComponent } from "react";
import { withPrefix } from "gatsby";
class RedirectIndex extends PureComponent {
render() {
const returnRedirect = () => {
if (typeof window !== "undefined") {
const getLocale = locale();
const setLocale = getLocale === "pl" ? "pl" : "en";
const redirect = withPrefix(`/${setLocale}/`);
return <Redirect to={redirect} />;
}
return <div />;
};
return returnRedirect();
}
}
export default RedirectIndex;
Hey @KyleAMathews Maybe I can work on this.
Do you have some steps of how I can reproduce it?
Hey I was looking at this today, but it looks like this has since changed from the initial comment by @KyleAMathews https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/cache-dir/navigation.js#L129. Does this remedy the issue or is there further work needed?
Any updates on this? Is there a possible workaround to avoid the 404-flash? I wouldn't mind spending some time on trying to fix the issue (it's currently blocking a Gatsby v1 > v2 upgrade) but a bit at loss on where to start. Could you give any hint, @KyleAMathews?
I would also like to try solving this issue, do we have any steps to reproduce this?
https://dc-hsda.ml this page flashes a 404 before loading the main site. I am using a bare bones app generated from the cli. Here's the repo.
EDIT: Note that I don't get this on gatsby serve
but I'd rather not run a server to serve static files.
We just launched (last night!) a full rewrite of our product using Gatsby and we are seeing the 404 page every time the user loads a client-only route -- either by directly navigating to a client-only route or by clicking reload in the browser.
We've got about 100,000 monthly active users, so plenty of surface area to try solutions that you post in this thread. Happy to provide any details that may be helpful, everything from our S3 / Cloudfront config to our app routing structure. Just let me know if there's anything in particular you'd like to know.
Thanks for looking into this issue!
@kiley0 did you setup any server rewrites for your client-only route? If not this usually means that server will not find page in normal directory structure and will serve 404 page and later on when gatsby/react mounts it will find client-only route and update DOM with proper route
@pieh thanks for quick reply. We namespaced almost all of our client-only routes to always be a path that starts with /app/*
, and we originally added a rule to always return /app/index.html
when a user tried to directly visit a client-only route (or reload). Our pages/app.js
file is the file that has all of our top-level <Router>
and <Route>
s, so our thought was that it would properly handle any client-only route.
We removed that rule because we have just a handful of client-only routes that _don't_ match that /app/*
path structure in order to maintain compatibility with our old site's URL pattern. We are able to generate about 95% of these pages that match the old URLs, but we're stuck having to dynamically render about 5% of them.
So, perhaps we should go back to the first solution of having the server return /app/index.html
instead of 404.html
for the client-only routes, and come up with some other solution for these legacy URLs that have to be dynamically rendered.
Thanks for your thoughts, let me know if any ideas popped out at you. In the meantime, we'll try server rewrite to /app/index.html
for client-only routes.
I've also run into this issue and will set up a repro repo to help with identifying the problem.
For SEO purposes a crawler would observe this page as 404: Not Found, right?
I would guess so @yanneves, unless the crawler runs client-side javascript. So if I understand it correctly, the only valid workaround to avoid flashing a 404 is to add redirect rules on the server?
Hiya!
This issue has gone quiet. Spooky quiet. 👻
We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
Thanks for being a part of the Gatsby community! 💪💜
Hi! I haven't found any resolution to this and it doesn't seem like a PR that fixes this has been made.
Same problem here.
Having the same problem.
I've mapped all the paths to run as client-only:
page.matchPath = "/*"
createPage(page)
And having simple:
<Router>
<Home path="/" />
<Login path="/login" />
</Router>
And requesting /login
temporary shows Home component, before Login component is loaded.
For me it only happens on build && serve
I'm also having the same problem with a Gatsby and Netlify setup.
I have a single page at /courses/
, but also child pages dynamically built that exist at /courses/:slug/
.
In my Netlify redirects, I'm stating
/courses/:slug/* /courses/:slug/index.html 200
But, refreshing on any client route after the slug (like /courses/course-name/checkout
) gives a momentary 404.
This will prevent a flash of 404 page content by simply checking if the window
is available during gatsby build
.
pages/404.js
import React from "react";
import SEO from "../components/seo";
const browser = typeof window !== "undefined" && window;
const NotFoundPage = () => {
return (
browser && (
<div>
<SEO title="404 Page not found" />
<h1>404 Error content...</h1>
</div>
)
);
};
export default NotFoundPage;
Works well with this plugin too
@samburgers Fantastic! In initial testing, it seems to work just fine 👍
Just as a data point, we previously added fix https://github.com/gatsbyjs/gatsby/issues/5329#issuecomment-484741119 but we were recently having problems with our 404 page on production with the latest version of Gatsby. Removing the const browser = typeof window !== "undefined" && window;
section fixed the issue, and it appears we now don't have the same flashing problem anymore.
An additional data point, I had an AWS CloudFront distribution backing an S3 bucket with gatsby content.
I'd added a rule to route all 403s as 404s and serve /404.html. (instead of the gnarly permission denied messages)
On the index page of any of the folders, this issue popped up.
What I ended up doing is enabling the static site in S3 and making CloudFront back that URL instead of integrating it with an S3 origin directly.
my co-worker come up with a workaround for this, using Match
from @reach/router
and passing the slug
from the match
prop to the component
import React from 'react'
import { Match } from '@reach/router'
import Layout from 'components/common/Layout'
export default () => (
<Layout>
<Match path="/app/:slug">
{({ match }) => <App slug={match && match.slug} />}
</Match>
</Layout>
)
then showing a loader when the window scope isn't available (for static SSR), else redirect to 404 page.
import React from 'react'
import Spinner from 'components/common/Spinner'
const IS_IN_BROWSER = typeof window !== 'undefined'
export default ({ slug }) => {
if (!slug) {
if (IS_IN_BROWSER) navigate('/404')
// For SSR rendering
return <Spinner />
}
.....
Works like a charm 👌
@Nessworthy With CloudFront accessing S3 buckets directly it only serves index.html for the root of the domain, not for sub-folders. Their suggested hack is to use rewrite rules in Lambda@Edge.
Generally the real fix for this problem is for the static hosting provider to serve index.html
correctly and do rewrites for client only routes. This enables the maximum benefit of SSR/hydration for SEO and performance.
using selenium testing and graphql we can remove 404 error on opening the site.
I'm working on upgrading our site to v2, and have just noticed the flash of 404 when following internal gatsby links to URLs that redirect. Any ideas on how I could help fix this rather than just workaround the issue?
A bit of background on why we'd like this:
Our site is structured as /support/app-name/section/article-name/
. The support homepage, our footer component (used across a few sites) and marketing emails all have links to /support/app-name
, which redirects to the first article in that app's documentation (e.g. https://moleskinestudio.com/support/flow/ - the current gatsby v1 website). The slug for the first article in each section may change, which is why I haven't used the full URL - having the shorter redirect is a nice convenience. (Like if https://www.gatsbyjs.org/docs/mdx/ page redirected to https://www.gatsbyjs.org/docs/mdx/getting-started/ rather than being a separate page)
I've set up server-side redirects (using the netlify plugin), which works fine when coming to the site externally, but when someone comes from an internal link from the site footer then they see the 404 page flash.
After some debugging it turns out that the issue I was seeing in my previous comment only happens when you use the Link component from @reach/router. I changed over my component library to use the Link from gatsby, and it follows the redirects fine 😃
I also see this issue.
I have a cloudflare 301 redirect from example.com to blog.example.com/
When I natigate to example.com the service worker returns a 200, but when I browse incognito I get the 301 redirect as expected.
Samburgers's solution worked for me on cloudfront / S3, but I had to customize 403 errors in cloudfront to return a 404 with /404.html. On another tutorial it recommended sending 200 OK headers with /404.html, but react wouldn't find the page resource and wouldn't load unless it was a proper 404 header. Thank you--
Hi there! Anyone has a solution about this issue? The @samburgers solution works, but it's only hide the 404 page. I have the same issue, but when I deploy gatsby to S3/Cloudfront.
@smakosh Can you give me more details about your solution? Which files did you change?
The first snippet is in your page that is not generated during build time but rendered by the client, the second code snippet is within your component
I can help if you add me as collaborator to your repository or show me only your "app" page and how your routes are handled
@smakosh thanks! What causes the page not be generated during build? I think I'll be SEO problems with this solution.
My app use the basic gatsby boilerplate. I have a subdirectory in pages directory. When I access this subpage the 404 page is temporarily shown
@smakosh thanks! What causes the page not be generated during build? I think I'll be SEO problems with this solution.
My app use the basic gatsby boilerplate. I have a subdirectory in pages directory. When I access this subpage the 404 page is temporarily shown
Got it, in our case, it was happening on the app (https://www.gatsbyjs.org/blog/2018-10-15-beyond-static-intro/)
But I think you could solve that the same way, do you mind attaching a screenshot of your page file tree?
@smakosh when I access program/digital
the 404 page is temporarily shown. I'm buiding using prefixPaths: gatsby build --prefix-paths
Is that a static page or a component with routes?
@smakosh is a static page, but the submenu
component uses globalHistory
from @reach/router
@smakosh any thoughts?
My preloaded page is <link as="script" rel="preload" href="https://xxxx.cloudfront.net/front/component---src-pages-404-js-93ad72fcacf3fcd0b464.js" />
I tried reproducing your use case here: https://codesandbox.io/embed/goofy-lake-i0c7z?codemirror=1
Can you fork it & implement what you have from your side?
@samburgers
This will prevent a flash of 404 page content by simply checking if the
window
is available duringgatsby build
.
pages/404.js
import React from "react"; import SEO from "../components/seo"; const browser = typeof window !== "undefined" && window; const NotFoundPage = () => { return ( browser && ( <div> <SEO title="404 Page not found" /> <h1>404 Error content...</h1> </div> ) ); }; export default NotFoundPage;
Works well with this plugin too
i can confirm that this solved our issues with the 404 flash. i owe you a beer, sir.
@samburgers
This will prevent a flash of 404 page content by simply checking if the
window
is available duringgatsby build
.
pages/404.js
import React from "react"; import SEO from "../components/seo"; const browser = typeof window !== "undefined" && window; const NotFoundPage = () => { return ( browser && ( <div> <SEO title="404 Page not found" /> <h1>404 Error content...</h1> </div> ) ); }; export default NotFoundPage;
Works well with this plugin too
i can confirm that this solved our issues with the 404 flash. i owe you a beer, sir.
Yesss ... Thank you for that!!!
This will prevent a flash of 404 page content by simply checking if the
window
is available duringgatsby build
.
pages/404.js
import React from "react"; import SEO from "../components/seo"; const browser = typeof window !== "undefined" && window; const NotFoundPage = () => { return ( browser && ( <div> <SEO title="404 Page not found" /> <h1>404 Error content...</h1> </div> ) ); }; export default NotFoundPage;
Works well with this plugin too
Can confirm this resolved the issue.
Hello I am Param Gabhawala ,
Redirect the 404 error: Redirecting users to another relevant page is the easiest way to fix 404 errors on your site. Just make sure you redirect them to something relevant — don't just send them back to your homepage.
Most helpful comment
This will prevent a flash of 404 page content by simply checking if the
window
is available duringgatsby build
.pages/404.js
Works well with this plugin too