MDX 및 Next.js 로 블로그를 만들고 있지만 Markdown 콘텐츠를 렌더링 할 수 없습니다. 블로그 게시물은 마크 다운 콘텐츠를 string
.
여기에 내 완전한 소스 코드가 있습니다 → https://github.com/deadcoder0904/blog-mdx-next/
다음 폴더 구조가 있습니다.
.
|-- README.md
|-- components
| `-- Image.js
|-- next.config.js
|-- package-lock.json
|-- package.json
|-- pages
| |-- _app.js
| |-- blog
| | `-- [slug].js
| |-- dark.css
| |-- index.js
| `-- new.css
|-- posts
| |-- blog
| | |-- hello-world
| | | |-- Rustin_Cohle.jpg
| | | `-- index.mdx
| | `-- shit-world
| | `-- index.mdx
| `-- tutorials
| `-- console-log-in-javascript
| `-- index.mdx
|-- prettier.config.js
`-- utils
`-- mdxUtils.js
posts/
폴더에 모든 콘텐츠가 있습니다.
2 개의 폴더가 있습니다. blog/
&tutorials/
각 게시물은 blog/
또는 내부의 자체 폴더에 있습니다 tutorials/
. 다음과 같이 보입니다.
I want to render my posts/blog/hello-world/index.mdx
post at blog/hello-world
location so I made blog/[slug].js
file.
The contents of it are as follows:
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { MDXProvider } from '@mdx-js/react'
import { BLOG_PATH, blogFilePaths } from '../../utils/mdxUtils'
import { Image } from '../../components/Image'
const MDXComponents = { Image }
const Blog = ({ source, frontMatter }) => {
return (
<div>
<h1>{frontMatter.title}</h1>
<MDXProvider components={MDXComponents}>{source}</MDXProvider>
</div>
)
}
export async function getStaticPaths() {
const paths = blogFilePaths.map((path) => {
const split = path.split('/')
const slug = split[split.length - 2]
return {
params: {
slug,
},
}
})
return {
paths,
fallback: false,
}
}
export const getStaticProps = async ({ params }) => {
const { slug } = params
const blogFilePath = path.join(BLOG_PATH, `/blog/${slug}/index.mdx`)
const source = fs.readFileSync(blogFilePath)
const { content: mdx, data } = matter(source)
if (!blogFilePath) {
console.warn('No MDX file found for slug')
}
return {
props: {
source: mdx,
frontMatter: data,
},
}
}
export default Blog
The important part is:
<MDXProvider components={MDXComponents}>{source}</MDXProvider>
I thought this would render markdown content but it only displays markdown content as a string
.
You can check the output at https://codesandbox.io/s/github/deadcoder0904/blog-mdx-next?file=/pages/blog/%5Bslug%5D.js by clicking any blog post.
It displays the following when I click on Hello World
post:
How do I actually render the content?
I looked at other Github repos like Tailwind CSS Blog & it works fine for them but I am not sure how it works sadly :(
I do know that I have to convert the source
prop in Blog
or mdx
in getStaticProps
but I don't see Tailwind doing it either.
I think this is what you're looking for https://github.com/vercel/next.js/discussions/13901
You'll need to install this package npm i next-mdx-remote
and make these changes to your code:
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import renderToString from 'next-mdx-remote/render-to-string'
import hydrate from 'next-mdx-remote/hydrate'
import { BLOG_PATH, blogFilePaths } from '../../utils/mdxUtils'
import { Image } from '../../components/Image'
const components = { Image }
const Blog = ({ source, frontMatter }) => {
const content = hydrate(source, { components })
return (
<div>
<h1>{frontMatter.title}</h1>
{content}
</div>
)
}
...
export const getStaticProps = async ({ params }) => {
const { slug } = params
const blogFilePath = path.join(BLOG_PATH, `/blog/${slug}/index.mdx`)
const source = fs.readFileSync(blogFilePath, 'utf-8');
const { content, data } = matter(source);
const mdxSource = await renderToString(content, { components });
if (!blogFilePath) {
console.warn('No MDX file found for slug')
}
return {
props: {
source: mdxSource,
frontMatter: data,
},
}
}
export default Blog
But then you will have an issue when referencing assets inside your mdx files, the tailwind blog solves this by adding a loader for assets, unfortunately next-mdx-remote
doesn't seem to support imports inside MDX (or probably need a specific configuration) so you'll have to move your images to the public folder, something like public/blog/Rustin_Cohle.jpg
Tailwind 블로그와의 차이점은 Dynamic SSG를 사용하고 있다는 것입니다.
또한 완전히 테스트하지 않은 또 다른 접근 방식이 있습니다 https://github.com/vercel/next.js/issues/9524#issuecomment-580239600
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다