在 Next JS 中使用来自 `@mdx-js/react` 的 `MDXProvider` 时,MDX 博客只显示降价内容而不是渲染它
MDX blog just displays markdown content instead of rendering it while using `MDXProvider` from `@mdx-js/react` in Next JS
我正在使用 MDX & Next.js 创建博客,但我无法呈现 Markdown 内容。博客 post 只是将 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/
每个 post 都在 blog/
或 tutorials/
中各自的文件夹中。看起来像:
我想在 blog/hello-world
位置渲染我的 posts/blog/hello-world/index.mdx
post,所以我创建了 blog/[slug].js
文件。
内容如下:
pages/blog/[slug].js
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
重要的部分是:
<MDXProvider components={MDXComponents}>{source}</MDXProvider>
我认为这会呈现 markdown 内容,但它只将 markdown 内容显示为 string
。
您可以通过单击任何博客 post 查看 https://codesandbox.io/s/github/deadcoder0904/blog-mdx-next?file=/pages/blog/%5Bslug%5D.js 的输出。
点击Hello World
post显示如下:
我如何实际呈现内容?
我查看了其他 Github 存储库,例如 Tailwind CSS Blog & it works fine for them,但我不确定它是如何工作的:(
我知道我必须转换 Blog
中的 source
道具或 getStaticProps
中的 mdx
但我 don't see Tailwind 也这样做了。
我想这就是您要找的东西https://github.com/vercel/next.js/discussions/13901
您需要安装此软件包 npm i next-mdx-remote
并对您的代码进行以下更改:
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
但是当您在 mdx 文件中引用资产时,您会遇到问题,tailwind 博客通过 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 解决了这个问题,例如 public/blog/Rustin_Cohle.jpg
与 tailwind 博客的不同之处在于您使用的是 Dynamic SSG
此外,还有另一种方法我没有完全测试https://github.com/vercel/next.js/issues/9524#issuecomment-580239600
我正在使用 MDX & Next.js 创建博客,但我无法呈现 Markdown 内容。博客 post 只是将 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/
每个 post 都在 blog/
或 tutorials/
中各自的文件夹中。看起来像:
我想在 blog/hello-world
位置渲染我的 posts/blog/hello-world/index.mdx
post,所以我创建了 blog/[slug].js
文件。
内容如下:
pages/blog/[slug].js
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
重要的部分是:
<MDXProvider components={MDXComponents}>{source}</MDXProvider>
我认为这会呈现 markdown 内容,但它只将 markdown 内容显示为 string
。
您可以通过单击任何博客 post 查看 https://codesandbox.io/s/github/deadcoder0904/blog-mdx-next?file=/pages/blog/%5Bslug%5D.js 的输出。
点击Hello World
post显示如下:
我如何实际呈现内容?
我查看了其他 Github 存储库,例如 Tailwind CSS Blog & it works fine for them,但我不确定它是如何工作的:(
我知道我必须转换 Blog
中的 source
道具或 getStaticProps
中的 mdx
但我 don't see Tailwind 也这样做了。
我想这就是您要找的东西https://github.com/vercel/next.js/discussions/13901
您需要安装此软件包 npm i next-mdx-remote
并对您的代码进行以下更改:
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
但是当您在 mdx 文件中引用资产时,您会遇到问题,tailwind 博客通过 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 解决了这个问题,例如 public/blog/Rustin_Cohle.jpg
与 tailwind 博客的不同之处在于您使用的是 Dynamic SSG
此外,还有另一种方法我没有完全测试https://github.com/vercel/next.js/issues/9524#issuecomment-580239600