Next.js route mismatch in prod build but not in dev - next.js

I'm using Next.js and trying to implement incremental static regeneration. My pages structure is:
pages
- [primary]
- article
- [...slug.js]
and my [...slug.js]
import Head from 'next/head'
export default function Article({ post }) {
if (!post) {
return 'loading'
}
const data = post[0];
return (
<div className="container mx-auto pt-6">
<Head>
<title>{`${data.title.rendered}`}</title
</Head>
<main>
<div>{data.content.rendered}</div>
</main>
</div >
)
}
export async function getStaticPaths() {
return {
paths: [{ params: { primary: '', slug: [] } }],
fallback: true,
};
}
export async function getStaticProps({ params }) {
const slug = params.slug[0];
const res = await fetch(`https://.../?slug=${slug}`)
const post = await res.json()
return {
props: { post },
revalidate: 1,
}
}
This works locally when I pass route like: localhost:3000/dance/article/lots-of-dancers-dance-in-unison, it correctly passes the slug and I can query the CMS no problem. But when I run build I get:
Error: Requested and resolved page mismatch: //article /article at normalizePagePath

This is because the static path you are providing for primary is '' (empty).
For empty string value for primary, the static path becomes //article which resolves to /article. This is what the error says.
Though this works in development, it will give the said error in Prod build.
Add a value to the path and it should work!
paths: [{ params: { primary: 'abc', slug: [] } }],

Related

nextjs dynamic routes doesn't work with next-i18next

I just added next-i18next in my nextjs project following the official guide and everything seemed to be in order, but when I change the language from default (Italian) to English and I go to the detail of an entity then I get 404. This happens only with the dynamic routes and only with the language that is not the default one.
I am going to show you more details.
My next-i18next.config.js file:
module.exports = {
i18n: {
defaultLocale: "it",
locales: ["it", "en"],
},
};
[id].tsx
//My NextPage component...
export async function getStaticPaths() {
const paths = await projects.find()?.map((_project) => ({
params: { id: _project.id + "" },
}));
return {
paths,
fallback: false,
};
}
export async function getStaticProps({
locale,
...rest
}: {
locale: string;
params: { id: string };
}) {
const project = await projects.findOne({id: rest.params.id})
const seo: Seo = {
//...
};
//This row is not the problem, since it persists even if I remove it. Also I am sure that the project exists.
if (!project?.id) return { notFound: true };
return {
props: {
...(await serverSideTranslations(locale, [
"common",
"footer",
"projects",
])),
seo,
project,
},
};
}
index.tsx (under projects folder)
const Projects: NextPage<Props> = ({ /*...*/ }) => {
//...
const router = useRouter();
return <button onClick={() =>
router.push({
pathname: `/projects/[slug]`,
query: { slug: project.slug },
})
}>Read more</button>
}
Also I get the error Error: The provided 'href' (/projects/[slug]) value is missing query values (slug) to be interpolated properly. when I try to change the language while I am in the detail of the project with the italian language set, but I think I did it right according to this doc. As I said before, instead, if I try to go into the dynamic route after having changed the language to "en" then I go to 404 page.
Do you have any suggestions to solve this problem?
I solved this by updating the mothod getStaticPaths to:
export async function getStaticPaths({ locales }: { locales: string[] }) {
const projects = getProjects({ locale: "it" });
const paths = projects.flatMap((_project) => {
return locales.map((locale) => {
return {
params: {
type: _project.slug,
slug: _project.slug,
},
locale: locale,
};
});
});
return {
paths,
fallback: true,
};
}
So there must be passed the locale into the paths.

next js dynamic page routing working in localhost but giving file not found error in production

This is part of my next js project. This website is running perfectly on localhost but when i deploy it on vercel, the /blogs/book/chapter page is giving me file not found enter image description here500 error.
Hosted Page - Website
Source Code - GitHub
Dynamic Routing Folder Structure
Page Structure
chapter.js
import fs from "fs";
import path from "path";
import Head from "next/head";
import DefaultErrorPage from "next/error";
import { useRouter } from "next/router";
import matter from "gray-matter";
import { marked } from "marked";
import styles from "../../../../styles/blog/Chapter.module.css";
import { capitalise } from "../../../../components/blog/Capitalise";
import BlogPostBottom from "../../../../components/blog/BlogPostBottom";
export default function Chapter({ book, chapter, frontmatter, content }) {
// Destructuring
const { description } = frontmatter;
// Router Variable
const router = useRouter();
// If fallback then show this
if (router.isFallback) {
// if (router.isFallback || !book || !chapter || !content) {
return <div>Loading...</div>;
}
if (!book || !chapter || !content || !frontmatter) {
return (
<div>
<DefaultErrorPage statusCode={404} />
</div>
);
}
return (
<div className={styles.bookChapter}>
<Head>
<title>{`${capitalise(chapter)} | ${capitalise(
book
)} | Blog | Manav Goyal`}</title>
<meta
name="description"
content={`Read Blog about this book ${book} covering chapter ${chapter} of topics ${description}`}
/>
</Head>
<h1>{`${capitalise(chapter)} - ${capitalise(book)}`}</h1>
<section
className={styles.bookChapterContent}
dangerouslySetInnerHTML={{ __html: marked(content) }}
></section>
<BlogPostBottom slug={`/blog/${book}`} />
</div>
);
}
export async function getStaticPaths() {
return {
paths: [{ params: { book: "css", chapter: "bootstrap" } }],
// paths: [],
fallback: true,
};
}
// Web crawlers, won't be served a fallback and instead the path will behave as in fallback: 'blocking'
// fallback: true is not supported when using `next export`
export async function getStaticProps({ params }) {
const { book, chapter } = params;
let chapterPost = null;
try {
chapterPost = await fs.promises.readFile(
path.join(`posts/${book}/${chapter}.md`),
"utf-8"
);
} catch (err) {}
const { data: frontmatter, content } = matter(chapterPost);
return {
props: {
book,
chapter,
frontmatter,
content,
},
// redirect: {
// destination: `/blog/${book}`,
// permanent: false,
// },
// revalidate: 1,
};
}
Chapter.defaultProps = {
book: "css",
chapter: "bootstrap",
frontmatter: { description: "CSS", id: "1" },
content: "Error",
};
Posts Folder Structure
Posts Folder Structure
Error
Console
Vercel Function Log

My website deployed on Vercel keeps giving me the "429: TOO_MANY_REQUESTS" errors. What could be going wrong, how can I debug this?

Occassionally (maybe about half the time) when I load a page on the website I'm working on, I'm getting an error that looks like this.
429: TOO_MANY_REQUESTS
Code: INTERNAL_FUNCTION_RATE_LIMIT
ID: lhr1::258d8-1638206479250-0a01c8648601
My website hasn't been launched yet, almost nobody visits it but me, so it can't be having too much traffic yet.
The page I'm loading has a getServerSideProps() function that does only one thing - uses prisma to fetch posts from my database, which are sent to my component to be rendered.
I can't imagine what could be causing too many requests.
My vercel usage stats look like this.
What am I doing wrong? What could be causing this? How can I debug this?
For reference, below is all my relevant code. Any chance you could take a look at it and let me know if you have any ideas on what could be happening?
index.tsx has getServerSideProps() function which calls a getPosts() function to fetch the posts.
import Layout from 'components/Layout/Layout'
import PostFeed from 'components/Posts/PostFeed'
import Subnav from 'components/Layout/Subnav'
import Pagination from 'components/Posts/Pagination'
import ProfileHeader from 'components/Users/ProfileHeader'
import TagHeader from 'components/Layout/TagHeader'
import HomeHeader from 'components/CTAs/HomeHeader'
import SubscribeBox from 'components/CTAs/SubscribeBox'
import AdBoxes from 'components/CTAs/AdBoxes'
export default function browse({ posts, postCount, username }) {
return (
<Layout subnav={<Subnav />}>
<PostFeed posts={posts} />
<Pagination postCount={postCount} />
<AdBoxes/>
<SubscribeBox />
<br />
</Layout>
)
}
import { getPosts } from 'prisma/api/posts/get-posts'
import config from 'config.json'
export async function getServerSideProps({ req, query }) {
const { username, sort, tag, search } = query
const { posts, postCount } = await getPosts({
published: true,
searchString: search,
username: username,
tagSlug: tag,
sort: sort,
skip: config.postsPerPage * (parseInt(query.page?.toString()) - 1 || 0),
take: config.postsPerPage,
})
return { props: { posts, postCount, username } }
}
get-posts.ts runs a prisma query and fetches the posts.
import prisma from 'prisma/prismaClient'
export async function getPosts({ username, published, tagSlug, searchString, sort, skip, take }) {
console.log(`Get posts. Sorting: ${sort}`)
// Filter posts by user (to show them on their profile)
let author
if (username) author = await prisma.user.findUnique({ where: { username } })
// Filter by tag
const tagFilter = tagSlug ? {
tags: { some: { slug: tagSlug } }
} : {}
// Search through posts
const search = searchString ? {
OR: [
{ title: { contains: searchString, mode: "insensitive", } },
{ body: { contains: searchString, mode: "insensitive", } },
{ tags: { some: { name: { contains: searchString, mode: "insensitive", } } } },
{ author: { username: { contains: searchString, mode: "insensitive", } } },
],
} : {}
let orderBy = [{ rank: 'desc' }]
if (sort === 'new') orderBy = [{ createdAt: 'desc' }]
if (sort === 'top') orderBy = [{ score: 'desc' }]
const allFilters = {
authorId: author?.id,
published: published,
...search,
...tagFilter,
}
const [posts, postCount] = await prisma.$transaction([
prisma.post.findMany({
where: allFilters,
orderBy: orderBy, //rank: 'desc' //score: 'desc'
take, skip,
include: {
tags: true,
author: {
select: {
username: true
}
},
upvoters: {
select: {
username: true
}
},
// Just for the comment counter
comments: {
select: {
id: true
}
}
}
}),
prisma.post.count({ where: allFilters })
])
return { posts, postCount }
}
the prismaClient which get-posts is using to connect to prisma
import { PrismaClient } from "#prisma/client";
// PrismaClient is attached to the `global` object in development to prevent
// exhausting your database connection limit.
//
// Learn more:
// https://pris.ly/d/help/next-js-best-practices
let prisma: PrismaClient
if (process.env.NODE_ENV === 'production') {
prisma = new PrismaClient()
} else {
if (!global.prisma) {
global.prisma = new PrismaClient()
}
prisma = global.prisma
}
export default prisma
Try going towards getInitialProps which will execute your function on the browser vs getServerSideProps which always goes to your function creating loops as customers refresh your page or traverse through the site.
As to why so many requests, i think as clients traverse your site, you are generating hits to your function in a loop.

NextJS - Categories (Tags) - Dynamic Pages

I'm using Next.js with Static Site Generation, and I've created a category (tags) component as shown below:
import Link from "next/link";
export default function CategorySection({ categories }) {
return (
<Wrapper>
<ContentWrapper>
<CategoryWrapper>
{categories.map((category) => {
return (
<>
{category.contentfulMetadata.tags.map((tag) => {
return (
<Link href={`/articles/categories/${tag.id}`}>
<Categories>{tag.name}</Categories>
</Link>
);
})}
</>
);
})}
</CategoryWrapper>
</ContentWrapper>
</Wrapper>
);
}
I would like to be able to create dynamic pages for all tags and show articles only related to the tag.
I have created my [slug].jsx file at the following location: /pages/articles/categories/[slug].jsx
[slug].jsx file below:
import { getArticles, getArticle } from "../../../utils/contentful";
export async function getStaticPaths() {
const data = await getArticles();
return {
paths: data.articleCollection.items.map((article) => ({
params: { slug: article.contentfulMetadata.tags.id },
})),
fallback: false,
};
}
export async function getStaticProps(context) {
const data = await getArticle(context.params.slug);
return {
props: { article: data.articleCollection.items[0] },
};
}
export default function Category({ article }) {
return <h1>{article.contentfulMetadata.tags.name}</h1>;
}
I get the following error when navigation by using the tags on my articles page:
Error: A required parameter (slug) was not provided as a string in getStaticPaths for /articles/categories/[slug]
How can I get it to create dynamic pages using the tags?
Error: A required parameter (slug) was not provided as a string in getStaticPaths for /articles/categories/[slug]
In your getStaticPaths you need to convert slug to string.
params: { slug: article.contentfulMetadata.tags.id.toString() }

How to provide an array in getStaticPaths?

I learn nextJS and I try to use dynamic routes with a catch-all route. However I'm running into a basic problem, I'm not sure how to supply the data as an array in getStaticPaths.
This is my current code:
import Link from 'next/link';
function test({ variable }) {
return (
<>
<div>
<h1>{variable.var}</h1>
<Link href="/">
<a>← Back</a>
</Link>
</div>
</>
);
}
export async function getStaticProps({ params }) {
const variable = params.variable;
return {
props: {
variable,
},
};
}
export async function getStaticPaths() {
return {
fallback: false,
paths: [
{
params: {
variable: 'testi',
},
},
],
};
}
export default test
And I'm getting the error:
Error: A required parameter (variable) was not provided as an array in getStaticPaths for /test/[...variable]
Any ideas?
Edit:
Forgot to add, my current file name is [...variable].js
Indeed it was stupid:
paths: [
{ params: { variable: ["testi"] } },
]

Resources