You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在gatsby-plugin-mdx v4中嵌入Frontmatter图片?

在gatsby-plugin-mdx v4中嵌入Frontmatter里的图片

背景

我之前实现过MDX文章的图片嵌入方案,在gatsby-plugin-mdx v3中,是通过将Frontmatter里的embedded图片数据传递给MDXRenderer来实现的,示例代码如下:

gatsby-plugin-mdx v3 示例模板

/*  Post.jsx @ gatsby-plugin-mdx v3 */
import React from "react"
import { graphql } from "gatsby"
import { MDXRenderer } from "gatsby-plugin-mdx"
import Layout from "@layouts/Layout"
import { postContainer } from "@modules/Post.module.scss"

export default function DefaultPostTemplate({ data, location }) {
  const post = data.mdx

  return (
    <Layout location={location} title={post.frontmatter.title} description={post.frontmatter.lead}>
      <article className={postContainer}>
        <MDXRenderer thumbnail={post.frontmatter.thumbnail} embedded={post.frontmatter.embedded}>
          {post.body}
        </MDXRenderer>
      </article>
    </Layout>
  )
}

export const data = graphql`
  query ($id: String!) {
    mdx(id: { eq: $id }) {
      id
      body
      frontmatter {
        key
        title
        computerDate: date(formatString: "YYYY-MM-DD")
        humanDate: date(formatString: "D. MMMM YYYY", locale: "nn")
        enHumanDate: date(formatString: "MMMM D, YYYY", locale: "en")
        lead
        label
        subtitle
        embedded {
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
  }
`

但升级到gatsby-plugin-mdx v4后,模板改为使用children渲染MDX内容,原有的MDXRenderer方式不再适用,当前v4模板如下:

gatsby-plugin-mdx v4 当前模板

/*  Post.jsx @ gatsby-plugin-mdx v4 */
import React from "react"
import { graphql } from "gatsby"
import Layout from "@layouts/Layout"
import { postContainer } from "@modules/Post.module.scss"

export default function DefaultPostTemplate({ data, children }) {
  const post = data.mdx

  return (
    <Layout title={post.frontmatter.title} description={post.frontmatter.lead}>
      <article className={postContainer}>
        {children}
      </article>
    </Layout>
  )
}

export const data = graphql`
  query ($id: String!) {
    mdx(id: { eq: $id }) {
      frontmatter {
        key
        title
        computerDate: date(formatString: "YYYY-MM-DD")
        humanDate: date(formatString: "D. MMMM YYYY", locale: "nn")
        lead
        label
        subtitle
        embedded {
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
  }
`

解决方案

在v4中,需要通过MDXProvider传递自定义组件并注入Frontmatter的图片数据,具体步骤如下:

1. 创建自定义图片组件

先写一个用来渲染Gatsby图片的组件,比如EmbeddedImage.jsx:

import { GatsbyImage } from "gatsby-plugin-image"

export default function EmbeddedImage({ imageData, alt = "" }) {
  return <GatsbyImage image={imageData} alt={alt} />
}

2. 修改Post模板,通过MDXProvider传递props

更新v4的Post模板,引入MDXProvider和自定义组件,把Frontmatter中的embedded图片数据注入到自定义组件中:

/*  Post.jsx @ gatsby-plugin-mdx v4 */
import React from "react"
import { graphql } from "gatsby"
import { MDXProvider } from "@mdx-js/react"
import Layout from "@layouts/Layout"
import { postContainer } from "@modules/Post.module.scss"
import EmbeddedImage from "@components/EmbeddedImage"

export default function DefaultPostTemplate({ data, children }) {
  const post = data.mdx

  // 定义要注入MDX的自定义组件
  const customComponents = {
    EmbeddedImage: (props) => (
      <EmbeddedImage 
        imageData={post.frontmatter.embedded.childImageSharp.gatsbyImageData} 
        {...props} 
      />
    )
  }

  return (
    <Layout title={post.frontmatter.title} description={post.frontmatter.lead}>
      <article className={postContainer}>
        <MDXProvider components={customComponents}>
          {children}
        </MDXProvider>
      </article>
    </Layout>
  )
}

export const data = graphql`
  query ($id: String!) {
    mdx(id: { eq: $id }) {
      frontmatter {
        key
        title
        computerDate: date(formatString: "YYYY-MM-DD")
        humanDate: date(formatString: "D. MMMM YYYY", locale: "nn")
        lead
        label
        subtitle
        embedded {
          childImageSharp {
            gatsbyImageData
          }
        }
      }
    }
  }
`

3. 在MDX文章中使用组件

现在可以在你的MDX文章里直接调用自定义组件渲染图片:

# 我的文章

这是一张来自Frontmatter的图片:
<EmbeddedImage alt="示例图片描述" />

处理多张图片的情况

如果embedded是图片数组,只需调整模板中的组件逻辑,比如传递整个数组,然后在MDX中指定索引:

// 模板中的customComponents调整
EmbeddedImage: ({ index, alt = "" }) => (
  <EmbeddedImage 
    imageData={post.frontmatter.embedded[index].childImageSharp.gatsbyImageData} 
    alt={alt} 
  />
)

// MDX中使用
<EmbeddedImage index={0} alt="第一张图" />
<EmbeddedImage index={1} alt="第二张图" />

内容的提问来源于stack exchange,提问作者Magnus Kolstad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:03:21