Gatsby搭建博客时MDX无法渲染仅显纯文本,报Element type is invalid错误
Gatsby MDX内容无法渲染为HTML的解决方案
问题核心
你当前遇到两个关键问题:
- MDX内容以纯文本形式显示:直接渲染未编译的原始
body字段,未使用MDX专用渲染组件处理 - "Element type is invalid"错误:源于插件配置冲突、MDX组件导入错误或数据传递方式不合理
修复步骤
1. 清理gatsby-config.js的插件冲突
配置中重复注册了gatsby-plugin-mdx和gatsby-transformer-remark,会导致MDX编译逻辑混乱,修改后配置如下:
module.exports = { siteMetadata: { title: `My Online Portfolio`, description: `my home on the web`, siteUrl: `https://evilsaint.cloud`, social: { twitter: `https://twitter.com/_EvilSaint_` }, }, plugins: [ `gatsby-plugin-image`, `gatsby-plugin-sitemap`, `gatsby-plugin-sharp`, `gatsby-transformer-sharp`, { resolve: 'gatsby-plugin-mdx', options: { extensions: [`.mdx`, `.md`], gatsbyRemarkPlugins: [ { resolve: `gatsby-remark-highlight-code`, options: { terminal: "ubuntu", }, }, ], }, }, { resolve: 'gatsby-source-filesystem', options: { "name": "images", "path": "./src/images/" }, __key: "images" }, { resolve: 'gatsby-source-filesystem', options: { "name": "pages", "path": "./src/pages/" }, __key: "pages" }, { resolve: 'gatsby-source-filesystem', options: { "name": `blogs`, "path": `${__dirname}/src/blog/`, }, __key: "blogs" } ] };
2. 修改createPages逻辑,传递slug而非完整node
不要将整个MDX节点传入context,仅传递slug即可,让模板通过graphql查询编译后的MDX内容:
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions const path = require('path') const result = await graphql( ` query AllQueries { site { siteMetadata { title } } allMdx(sort: {fields: [frontmatter___date], order: DESC}) { nodes { fields { slug } frontmatter { date(formatString: "Do MMMM YYYY ") title description } } } } ` ) const blogPostTemplate = path.resolve(`./src/templates/blog-post.js`) const articles = result.data.allMdx.nodes articles.forEach((node, index) => { createPage({ path: `/blog${node.fields.slug}`, component: blogPostTemplate, context: { slug: node.fields.slug, prev: index === 0 ? null : articles[index - 1], next: index === articles.length - 1 ? null : articles[index + 1] }, }) }) }
3. 改造博客模板,用MDXRenderer渲染编译内容
首先安装必要依赖(未安装时执行):
npm install @mdx-js/react gatsby-plugin-mdx
修改模板代码,通过graphql查询MDX的编译后内容,并用MDXRenderer渲染:
import React from "react"; import { Link, graphql } from "gatsby"; import { MDXRenderer } from "gatsby-plugin-mdx"; import Layout from "../components/layout"; function BlogPost({ data, pageContext }) { const post = data.mdx const prev = pageContext.prev ? { url : `${pageContext.prev.fields.slug}`, title : pageContext.prev.frontmatter.title } : null const next = pageContext.next ? { url : pageContext.next.fields.slug, title : pageContext.next.frontmatter.title } : null return ( <Layout> <div className="card"> <Link className="card-link" to={`.${post.fields.slug}`}> <h2 className="card-title">{post.frontmatter.title}</h2> </Link> <p className="card-date">{post.frontmatter.date}</p> <p className="card-description">{post.frontmatter.description}</p> <MDXRenderer>{post.body}</MDXRenderer> <nav> {next && <Link to={`..${next.url}`} className="previous"> <span>< {next.title} </span> </Link> } {prev && <Link to={`..${prev.url}`} className="next"> <span>{prev.title} ></span> </Link> } </nav> </div> </Layout> ) } export const query = graphql` query($slug: String!) { mdx(fields: { slug: { eq: $slug } }) { fields { slug } frontmatter { date(formatString: "Do MMMM YYYY ") title description } body } } ` export default BlogPost
4. 验证MDX v2兼容性
确保gatsby-plugin-mdx版本为4.x及以上(支持MDX v2),查看package.json:
"gatsby-plugin-mdx": "^4.0.0"
版本过低时执行升级:
npm update gatsby-plugin-mdx
修复逻辑说明
- 重复插件会干扰Gatsby的MDX编译流程,必须清理
- 直接传递完整节点无法获取编译后的MDX组件,模板内查询才能拿到正确结果
MDXRenderer是Gatsby专用的MDX渲染组件,可将MDX语法转换为HTML元素和React组件
内容的提问来源于stack exchange,提问作者Berkay
相关产品推荐
相关产品推荐

