I'm trying to create a blog page to test nextjs
and created a dynamic route for the posts, which will be retrieved from Contentful. When navigating from Home page and clicking into a next/router
<Link />
component, the blog post loads correctly, but if I get the URL and try loading the page directly from browser address bar, I'll get 404.
Steps to reproduce:
1. git clone https://github.com/zeit/next-learn-demo.git
2. cd next-learn-demo/8-deploying
3. yarn
4. next build && next export
5. cd out
6. serve
7. Navigate to http://localhost:5000/p/learn-nextjs
8. See 404
Is this a limitation of NextJS (didn't find anything related to it on documentation) or do we need to configure anything else?
From NextJS 10 onwards, you don't have to return your 404 page explicitly thanks to the new flag notFound: true . You can use it at getStaticProps and getServerSideProps to auto trigger the default 404 page or your own custom 404 page as well.
For other errors, you can do the exact same thing with an _error.js file in the pages/ directory! The 404 error is special because it is always statically generated, but the others rely on the server. If you'd like to use the server-rendering aspects of Next.js on Netlify, check out our one-click install build plugin.
The href "goes" to the server to fetch the new page. If you're using some weird routing depending on the href to be different than the actual page location, you're gonna get a 404 the first time the server sees it, as it doesn't recognize that page, once the route kicks in and the correct page is rendered, it will show in the browser.
When you go directly to the URL, the correct route runs first, therefore no 404. When you use a Link instead, the default route runs first and then the correct one, hence the 404. This seems to be a problem with the express integration??
The real issue is that exporting a next
app will make it generate static HTML files. Even though it will still be able to request data before rendering the page, the set of available paths are not dynamic (they are generated during the next export
command). See this docs and this example.
Based on this, I have 2 possible solutions:
next build && next export
command every time a new blog post is published in Contentful;next
app and host a Node server that will handle the dynamic routes.That's because when you directly access the link or refresh the page then it add's a slash at the end of route. An next.js
doesn't recognize any route like that. To fix this, I hope there should be an easiest way to do that. However you can do this using custom server. Here is an example:
server.get("/about/", (req, res) => {
return app.render(req, res, "/about")
});
Hope this will help you.
To extend the answer provided by @Minoru, the official Next documentation covers this case in this example.
Using getStaticPaths
and getStaticProps
allows you to create dynamic pages at build time, avoiding the 404.
Example code for posts dynamic page:
import { GetStaticPaths, GetStaticProps } from 'next';
const Post = ({ post }) => {
const { id, content } = post;
return (
<div>
<h1>Post {id}</h1>
<p>{content}</p>
</div>
);
};
export const getStaticPaths: GetStaticPaths = async () => {
// Get all posts via API, file, etc.
const posts = [{ id: '1' }, { id: '2' }, { id: '3' }, { id: '4' }, { id: '5' }]; // Example
const paths = posts.map(post => ({
params: { id: post.id },
}));
return { paths, fallback: false };
};
export const getStaticProps: GetStaticProps = async context => {
const postId = context.params?.id || '';
// Get post detail via API, file, etc.
const post = { id: postId, content: `I'm the post with id ${postId}!` }; // Example
return { props: { post } };
};
export default Post;
When building the site with next build && next export
we will see in the out
folder that Next has created each post page
Then, when you navigate to /posts/3/
you will see the post with id 3
For reference, this docs page contains this case and many other use cases.
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