如何在Gatsby根路径渲染带格式的about.mdx内容?
问题描述
我是Gatsby和GraphQL的新手,正在探索相关技术。我想要将根目录下about.mdx的内容渲染到网站根路径,默认情况下Gatsby会根据about.mdx生成mysite.com/about这样的路径,但我希望网站的首页(根路径)能渲染与mysite.com/about相同的内容。
我原本的做法是在index.tsx文件中使用GraphQL提取about.mdx的内容,但将rawBody渲染到index.tsx时,显示效果和mysite.com/about由about.mdx渲染出的效果不一样,rawBody渲染的是无格式的纯文本。
效果对比
- 错误效果(rawBody渲染):

- 期望效果(about页面的正常渲染):

以下是我的index.tsx代码:
import React from 'react' import { Link, graphql } from 'gatsby' import { Wrapper, SectionTitle, Header, SectionSubTitle, SEO } from 'components' import { Layout } from 'layouts' import { Content } from 'layouts/components' import Helmet from 'react-helmet' import config from 'config/siteConfig' import Data from 'models/Data' import styled from 'styled-components' import { FeaturedPosts } from 'components/FeaturedPost' interface Props { data: Data } const HomePage = (props: Props) => { const { edges } = props.data.allMdx return ( <Layout> <Helmet title={`Blog | ${config.siteTitle}`} /> <SEO path="/" data={{ title: config.siteTitleAlt }} /> <Header> <SectionTitle> {config.siteTitle} <Line /> <SectionSubTitle>{config.siteDescription}</SectionSubTitle> </SectionTitle> </Header> <Wrapper> <Content> {edges.map((post) => ( <li key={post.node.frontmatter.title} style={{ listStyleType: 'none', margin: 0 }} > <DateTag dateTime={post.node.frontmatter.standardDate}> <p>{post.node.frontmatter.date} {post.node.rawBody}</p> </DateTag> </li> ))} </Content> </Wrapper> </Layout> ) } // Gatsby needs this default export to work. // eslint-disable-next-line import/no-default-export export default HomePage // export const query = graphql` // query { // allMdx( // sort: { fields: [frontmatter___date, frontmatter___title], order: DESC } // limit: 10 // ) { // totalCount // edges { // node { // fields { // path // } // frontmatter { // title // date(formatString: "MMMM D, YYYY") // standardDate: date(formatString: "YYYY-MM-DD") // } // excerpt(pruneLength: 200) // timeToRead // } // } // } // } // ` export const query = graphql` query { allMdx(filter: {id: {eq: "0d5c6066-a6d3-595d-8902-aedbfcdc2ce7"}, slug: {}}) { edges { node { id frontmatter { title } rawBody } } } } ` const Line = styled.hr` color: white; width: 5rem; margin: 0.5rem auto; height: 3px; ` const Title = styled.span` margin-right: 0.5rem; ` const DateTag = styled.time` color: rgba(0, 0, 0, 0.5); `
解决方案
问题出在直接渲染rawBody——它是未经编译的原始MDX文本,自然不会解析格式。要正确渲染MDX内容,有两种可行方案:
方案一:使用MDXRenderer渲染编译后的内容(保留/about路径)
1. 确保依赖安装配置完成
如果还没安装gatsby-plugin-mdx,先执行安装命令:
npm install gatsby-plugin-mdx @mdx-js/react
在gatsby-config.js中配置插件:
module.exports = { plugins: [ { resolve: `gatsby-plugin-mdx`, options: { // 可按需添加MDX插件配置 }, }, ], }
2. 修改GraphQL查询,获取编译后的body
将查询中的rawBody替换为body(这是Gatsby编译后的MDX内容):
export const query = graphql` query { allMdx(filter: {id: {eq: "0d5c6066-a6d3-595d-8902-aedbfcdc2ce7"}, slug: {}}) { edges { node { id frontmatter { title } body # 替换rawBody为body } } } } `
3. 引入并使用MDXRenderer组件
在index.tsx中导入MDXRenderer,并用它替代直接渲染rawBody:
import React from 'react' import { Link, graphql } from 'gatsby' import { MDXRenderer } from 'gatsby-plugin-mdx' // 新增导入 import { Wrapper, SectionTitle, Header, SectionSubTitle, SEO } from 'components' import { Layout } from 'layouts' import { Content } from 'layouts/components' import Helmet from 'react-helmet' import config from 'config/siteConfig' import Data from 'models/Data' import styled from 'styled-components' import { FeaturedPosts } from 'components/FeaturedPost' interface Props { data: Data } const HomePage = (props: Props) => { const { edges } = props.data.allMdx return ( <Layout> <Helmet title={`Blog | ${config.siteTitle}`} /> <SEO path="/" data={{ title: config.siteTitleAlt }} /> <Header> <SectionTitle> {config.siteTitle} <Line /> <SectionSubTitle>{config.siteDescription}</SectionSubTitle> </SectionTitle> </Header> <Wrapper> <Content> {edges.map((post) => ( <li key={post.node.frontmatter.title} style={{ listStyleType: 'none', margin: 0 }} > <h2>{post.node.frontmatter.title}</h2> {/* 使用MDXRenderer渲染编译后的内容 */} <MDXRenderer>{post.node.body}</MDXRenderer> </li> ))} </Content> </Wrapper> </Layout> ) } export default HomePage // 修改后的查询 export const query = graphql` query { allMdx(filter: {id: {eq: "0d5c6066-a6d3-595d-8902-aedbfcdc2ce7"}, slug: {}}) { edges { node { id frontmatter { title } body } } } } ` const Line = styled.hr` color: white; width: 5rem; margin: 0.5rem auto; height: 3px; ` const Title = styled.span` margin-right: 0.5rem; ` const DateTag = styled.time` color: rgba(0, 0, 0, 0.5); `
方案二:直接修改about.mdx的slug(无需修改index.tsx)
如果不需要保留/about路径,直接在about.mdx的frontmatter中设置根路径slug:
--- title: About slug: "/" --- # 这里是about.mdx的内容 ...
这样Gatsby会自动将about.mdx渲染到根路径,无需修改index.tsx。若需要同时保留/about路径和根路径的内容,则使用方案一。
内容的提问来源于stack exchange,提问作者NobinPegasus
相关产品推荐
相关产品推荐

