Issue with [slug]
Unanswered
Philippine Crocodile posted this in #help-forum
Philippine CrocodileOP
Hello,
I'm creating a simple blog using NextJS and MDX. For the routing, I have
I have a post that is on the
How can I fix it? I tried to create a page without
My code: https://github.com/ItsMeViipeR/nextlevel-tech
I'm creating a simple blog using NextJS and MDX. For the routing, I have
app/posts/[slug]/page.tsx that gets the post from the slug.I have a post that is on the
/posts/test-article route and locally it works. But, when I host my website on Vercel, it don't work.How can I fix it? I tried to create a page without
[slug] and it worked.My code: https://github.com/ItsMeViipeR/nextlevel-tech
50 Replies
@Philippine Crocodile Hello,
I'm creating a simple blog using NextJS and MDX. For the routing, I have `app/posts/[slug]/page.tsx` that gets the post from the slug.
I have a post that is on the `/posts/test-article` route and locally it works. But, when I host my website on Vercel, it don't work.
How can I fix it? I tried to create a page without `[slug]` and it worked.
My code: https://github.com/ItsMeViipeR/nextlevel-tech
It looks like your serverless function has timed out. This may happend thought this function: https://github.com/ItsMeViipeR/nextlevel-tech/blob/main/app/posts/%5Bslug%5D/page.tsx#L7
If you remove this function (temporary) and also remove the code that depend on that line, check if it's loading fine
If you remove this function (temporary) and also remove the code that depend on that line, check if it's loading fine
Philippine CrocodileOP
Here's the function
export const getPosts = async () => {
const files = await fs.readdir(postsDirectory);
const fileNames = files.filter((file) => file.endsWith(".mdx"));
const posts: Post[] = [];
for await (const fileName of fileNames) {
const fullPath = path.join(postsDirectory, fileName);
const fileContents = await fs.readFile(fullPath, "utf-8");
const frontmatter = matter(fileContents);
const safeData = PostSchema.safeParse(frontmatter.data);
if (!safeData.success) {
console.error(safeData.error.errors);
continue;
}
if (!safeData.data.published && process.env.NODE_ENV !== "development")
continue;
posts.push({
...safeData.data,
slug: fileName.replace(/^\d+-/, "").replace(".mdx", ""),
content: frontmatter.content,
});
}
return posts;
};
export const getPost = async (slug: string) => {
const posts = await getPosts();
return posts.find((post) => post.slug === slug);
};@Philippine Crocodile Here's the function
ts
export const getPosts = async () => {
const files = await fs.readdir(postsDirectory);
const fileNames = files.filter((file) => file.endsWith(".mdx"));
const posts: Post[] = [];
for await (const fileName of fileNames) {
const fullPath = path.join(postsDirectory, fileName);
const fileContents = await fs.readFile(fullPath, "utf-8");
const frontmatter = matter(fileContents);
const safeData = PostSchema.safeParse(frontmatter.data);
if (!safeData.success) {
console.error(safeData.error.errors);
continue;
}
if (!safeData.data.published && process.env.NODE_ENV !== "development")
continue;
posts.push({
...safeData.data,
slug: fileName.replace(/^\d+-/, "").replace(".mdx", ""),
content: frontmatter.content,
});
}
return posts;
};
export const getPost = async (slug: string) => {
const posts = await getPosts();
return posts.find((post) => post.slug === slug);
};
what's the result of this:
If you remove this function (temporary) and also remove the code that depend on that line, check if it's loading fine?
Philippine CrocodileOP
I can't try it for now, I'll tell you when I can, which result I get
Philippine CrocodileOP
Without using these functions, it works with slug
Philippine CrocodileOP
I found the error, the error is in the Mdx component
import { MDXRemote } from "next-mdx-remote-client/rsc";
import { MDX_COMPONENTS } from "./mdx-components";
import { rehypePlugin } from "./mdx-plugin";
import { Suspense } from "react";
export const Mdx = ({ children }: { children: string }) => {
return (
<Suspense fallback={<div>Loading...</div>}>
<MDXRemote
source={children}
options={{ mdxOptions: { rehypePlugins: rehypePlugin } }}
components={MDX_COMPONENTS}
/>
</Suspense>
);
};import { MdxYouTube } from "./MdxYouTube";
export const MDX_COMPONENTS = {
YouTube: MdxYouTube,
};import { YouTubeEmbed } from "@next/third-parties/google";
export const MdxYouTube = ({
id,
description,
}: {
id: string;
description?: string;
}) => {
return (
<div>
<YouTubeEmbed videoid={id} />
<p className="text-xs text-muted-foreground">{description}</p>
</div>
);
};The post in mdx
Philippine CrocodileOP
because I tried without calling the mdx component and it worked on vercel but not with the mdx component
the mdx component seems to call something that is not correct imo
@B33fb0n3 why do you think it's the mdx component?
Philippine CrocodileOP
so I found that but I don't know what can cause this issue
@Philippine Crocodile so I found that but I don't know what can cause this issue
I think it's more this line
that causes the timeout. I guess the reading is just to slow (or serving is to slow) and then the function times out.
Can you create some logging how long what kind of part from your app takes? With some console.logs and they contain a time. Maybe substract these times to calculate a relative time instead of an absolute time...
const fileContents = await fs.readFile(fullPath, "utf-8");that causes the timeout. I guess the reading is just to slow (or serving is to slow) and then the function times out.
Can you create some logging how long what kind of part from your app takes? With some console.logs and they contain a time. Maybe substract these times to calculate a relative time instead of an absolute time...
Philippine CrocodileOP
I don't think so because the title appears but the content don't appear
I added a Suspense to show the page without make the page crash
My Suspense don't prevent the crash lol
@Philippine Crocodile My Suspense don't prevent the crash lol
Can you share the error from your server console?
Also can you do this:
Also can you do this:
Can you create some logging how long what kind of part from your app takes? With some console.logs and they contain a time. Maybe substract these times to calculate a relative time instead of an absolute time...
Philippine CrocodileOP
Where do you want me to put the logs? before what and after what?
@B33fb0n3 before and after this line:
https://github.com/ItsMeViipeR/nextlevel-tech/blob/main/app/posts/%5Bslug%5D/page.tsx#L7
Philippine CrocodileOP
I can't see the logs because i'm in a client component
@Philippine Crocodile I can't see the logs because i'm in a client component
then check your server logs
@B33fb0n3 then check your server logs
Philippine CrocodileOP
@Philippine Crocodile Click to see attachment
can you show how you implemented the calculation of the time?
Philippine CrocodileOP
With
performance.now()Philippine CrocodileOP
@B33fb0n3 is it good?
@Philippine Crocodile With `performance.now()`
can you share the full code how you implemented the calculation of the time?
@B33fb0n3 can you share the full code how you implemented the calculation of the time?
Philippine CrocodileOP
const startTime = performance.now();
const post = await getPost(props.params.slug);
const endTime = performance.now();
console.log(`getPostDuration: ${endTime - startTime}ms`);@Philippine Crocodile ts
const startTime = performance.now();
const post = await getPost(props.params.slug);
const endTime = performance.now();
console.log(`getPostDuration: ${endTime - startTime}ms`);
thanks for sharing. Can you share the error from your server console?
https://nextjs-forum.com/post/1290001687414575231#message-1290238342297817132 (<----- click this)
https://nextjs-forum.com/post/1290001687414575231#message-1290238342297817132 (<----- click this)
@B33fb0n3 thanks for sharing. Can you share the error from your server console?
https://discord.com/channels/752553802359505017/1290001687414575231/1290238342297817132 (<----- click this)
Philippine CrocodileOP
all I have in the logs is this
@Philippine Crocodile all I have in the logs is this
now start your server and open the dev tools (F12). Then click on "performance". Then click this little icon on the top left (see attached). Wait a moment. Now check the results and take a look at which part is the biggest (see attached for an example). Now go into that part of your page and check why it takes so long to load
@Philippine Crocodile Click to see attachment
it looks like the content of the page takes to long to load and like that the timeout happens. That can happen thought the LCP (Largest Contentful Paint) an image that will be loaded or also the content itself (or both). So make sure to server your content thought a CDN. Do that for you content as well as your image
@B33fb0n3 it looks like the content of the page takes to long to load and like that the timeout happens. That can happen thought the LCP (Largest Contentful Paint) an image that will be loaded or also the content itself (or both). So make sure to server your content thought a CDN. Do that for you content as well as your image
Philippine CrocodileOP
a suspense with a loading component isn't enough?
@Philippine Crocodile a suspense with a loading component isn't enough?
no and it will never, because the stuff the browser need to download will stay the same. With or without suspense
@B33fb0n3 no and it will never, because the stuff the browser need to download will stay the same. With or without suspense
Philippine CrocodileOP
so can you send me an example code with my code for what you're telling me about?
import { MDXRemote } from "next-mdx-remote-client/rsc";
import { MDX_COMPONENTS } from "./mdx-components";
import { rehypePlugin } from "./mdx-plugin";
import { Suspense } from "react";
export const Mdx = ({ children }: { children: string }) => {
return (
<Suspense fallback={<div>Loading...</div>}>
<MDXRemote
source={children}
options={{ mdxOptions: { rehypePlugins: rehypePlugin } }}
components={MDX_COMPONENTS}
/>
</Suspense>
);
};@Philippine Crocodile so can you send me an example code with my code for what you're telling me about?
tsx
import { MDXRemote } from "next-mdx-remote-client/rsc";
import { MDX_COMPONENTS } from "./mdx-components";
import { rehypePlugin } from "./mdx-plugin";
import { Suspense } from "react";
export const Mdx = ({ children }: { children: string }) => {
return (
<Suspense fallback={<div>Loading...</div>}>
<MDXRemote
source={children}
options={{ mdxOptions: { rehypePlugins: rehypePlugin } }}
components={MDX_COMPONENTS}
/>
</Suspense>
);
};
I can't, because I don't have access to your file system. Your code itself looks not like the problem. It more looks like that the content that you are trying to serve takes too long to load and like that the serverless function times out
@Philippine Crocodile solved [like that](https://nextjs-forum.com/post/1290001687414575231#message-1290286908534034536) ?
@B33fb0n3 it looks like the content of the page takes to long to load and like that the timeout happens. That can happen thought the LCP (Largest Contentful Paint) an image that will be loaded or also the content itself (or both). So make sure to server your content thought a CDN. Do that for you content as well as your image
Philippine CrocodileOP
I don't really understand what you want me to do
@Philippine Crocodile I don't really understand what you want me to do
I want you to make sure to serve your content thought a CDN. Do that for you content, as well as your images
@B33fb0n3 I want you to make sure to serve your content thought a CDN. Do that for you content, as well as your images
Philippine CrocodileOP
the files that are in ./content?
@Philippine Crocodile the files that are in ./content?
the files that you are trying to load, yes
@B33fb0n3 the files that you are trying to load, yes
Philippine CrocodileOP
the files are loaded 'cause on
/posts i can access to the names and descriptions@Philippine Crocodile the files are loaded 'cause on `/posts` i can access to the names and descriptions
Yea, but you need to serve them correctly via a CDN.
Philippine CrocodileOP
how can I get files from cdn?
@Philippine Crocodile how can I get files from cdn?
you can select any CDN service you like and enter your origin url there. Then you get a CDN url. With that CDN Url you can get your files. For example like:
https://yourcdn.com/yourpicture.png
https://yourcdn.com/yourcontent.mdx
https://yourcdn.com/yourvideo.mp4@B33fb0n3 you can select any CDN service you like and enter your origin url there. Then you get a CDN url. With that CDN Url you can get your files. For example like:
https://yourcdn.com/yourpicture.png
https://yourcdn.com/yourcontent.mdx
https://yourcdn.com/yourvideo.mp4
Philippine CrocodileOP
it'll work for my mdx posts?
@Philippine Crocodile it'll work for my mdx posts?
it will work for every file
Philippine CrocodileOP
okay thanks I'll try it at home
Philippine CrocodileOP
I don’t really understand why using a cdn to store my posts will fix the issue because the issue don’t come from the post but from the mdx parsing
@Philippine Crocodile I don’t really understand why using a cdn to store my posts will fix the issue because the issue don’t come from the post but from the mdx parsing
This thread takes me so much energy. I guess you got everything that you need. Just to let you know: I won’t answer this thread anymore