We recently created a static app using Next.js, React and Netlify. Everything was fine until we stumbled upon 404 error for invalid routes.
This page indicates that we do not have any page defined for the route we entered. So as a fallback, Netlify redirects the user to its default 404.html
page.
Overriding Netlify's default 404.html
So you might be wondering if there was a way we could redirect the user to our custom 404 error page? After reading Netlify docs, we see that this can be done by creating a custom 404.html
page in our build directory. Once the file is found, Netlify will override its default 404.html
page with this custom 404.html
page that we just created. If we want to name this file something else then we will need to add the following configuration in netlify.toml
file (you can create one if you don't already have it), which should be present in your root directory.
[[redirects]]
from = "/*"
to = "/something.html"
status = 404
Detailed explanation for netlify.toml
file can be found here. I'll quickly explain the above code snippet to help understand it correctly.
-
[[redirects]]
: It is used to define redirection rule for our app, which controls how our pages are routed. Rules are defined using various properties likefrom
,to
,status
. -
from
: In our code above, we want to redirect all invalid routes(not defined by us) to404.html
Sofrom
is used to denote such invalid routes. -
to
: This is the error page that needs to be shown, it is by default set to404.html
for status 404. We can override it by defining a custom404.html
page. -
status
: This is error status, that needs to be applied for the above rule. We ask Netlify to showto
HTML page for allfrom
routes having error code as404
.
Redirecting to custom route for invalid routes
Since we are working with React, it would be good if we could use a component instead of HTML. Using component has many benefits like, we will be able to reuse any previously created component, like Header and Footer components. Also, the anchor links will need to be hard-coded to make the HTML file work as Next.js routes won't work inside HTML files. So let's find a way to use components.
We can create _error.js
which Next.js uses by default on the server to render any invalid routes. This component will be rendered like any other component, so we will have our default headers and footers and also all the routing will remain intact as we can access Next.js routing.
I have created a Github repo to demonstrate this component way of handling error so you can directly dive into the code and get some hands on.
If you check the code, our routes are as follows:
module.exports = {
"/": { page: "/" },
"/about": { page: "/about" },
"/async": { page: "/async" },
"/hn": { page: "/hn" },
"/error": { page: "/_error" }
};
We want to handle 404 error in such a way that it is consistent for local developments(i.e served using next -p port
) and also for production environments(served static files). On local, error is handled by Next.js(using yarn dev
), and Next.js uses _error
page from pages
folder to display error. You can read more about this here. Prod 404 error is handled by Netlify(using yarn build
command), so we also want a route for redirecting user for error, this is can be done using /error
route(you can keep this route as _error
to match netlify page name, I find /error
more readable).
Netlify configuration for this will look like:
[[redirects]]
from = "/*"
to = "/error"
status = 404
Now everything looks good so far and we seemed to have solved our problem. You can preview the code in action till this point here. There's one more thing left.
Introducing a twist π
Now if we try any invalid route of the form https://domain.netlify.com/error<any_text>
then we still see the Netlify 404.html
default page. Reason ?? seems its a bug. I reported this to the Netlify team (via email) and they accepted it was a bug. So how do we solve this bug?
This issue can be reproduced on this netlify build for the corresponding git commit
I tried all possible combination to fix this issue from netlify.toml
using redirects
rule. I tried forcing all the pages to /error
route(using force=true
), but the problem seemed very stubborn. Refer this link for more on force=true.
After some research, I found a hack to fix this issue until Netlify fixes it from their end. Here's what I did,
404.html
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0; url=https://netlfiy-react-example.netlify.com" />
<script type="text/javascript">
window.location.href = window.location.origin + "/_error";
</script>
<title>Page Redirection</title>
</head>
<body>
If you are not redirected automatically, follow this
<a href="https://netlfiy-react-example.netlify.com">Kiprosh</a>.
</body>
</html>
For routes of the form https://domain.netlify.com/error<any_text>
, this code snippet will override the default 404.html
of Netlify and once the user comes to this page, he will be redirected to our /error
route page using browser location API.
Hope this helped you and saved your time finding fixes from Netlify which do not exist yet.
Thanks for reading.