如何在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
相关产品推荐
相关产品推荐

