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

如何为Strapi的Markdown内容使用gatsby-image?能否优化react-markdown渲染的图片?

如何用gatsby-image优化Strapi Markdown内容中的图片

我之前也踩过这个坑——gatsby-remark-images只能处理由gatsby-transformer-remark解析的Markdown节点,如果你是直接用react-markdown渲染Strapi返回的原始Markdown文本,这个插件确实起不了作用。不过我们可以通过自定义react-markdown的图片渲染器,结合gatsby的图片处理能力来实现优化,具体步骤如下:

1. 基础配置准备

首先确保你已经安装并配置了必要的gatsby插件:

npm install gatsby-plugin-sharp gatsby-transformer-sharp gatsby-source-strapi react-markdown gatsby-plugin-image

然后在gatsby-config.js里配置Strapi数据源和图片处理插件:

module.exports = {
  plugins: [
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
    {
      resolve: `gatsby-source-strapi`,
      options: {
        apiURL: process.env.STRAPI_API_URL || "http://localhost:1337",
        accessToken: process.env.STRAPI_ACCESS_TOKEN,
        collectionTypes: [`post`], // 替换成你的Strapi内容类型,比如文章、博客等
        queryLimit: 1000,
      },
    },
  ],
};

2. 关联Strapi内容与图片节点

在Strapi中,确保你的内容类型(比如Post)不仅有Markdown字段(比如content),还关联了对应的图片字段(比如images,可以是多图类型)。这样gatsby-source-strapi会把Strapi上的图片下载到本地,并生成childImageSharp节点供gatsby-image使用。

接下来在页面的GraphQL查询中,同时获取Markdown内容和图片的gatsbyImageData:

query GetSinglePost($id: String!) {
  strapiPost(id: { eq: $id }) {
    title
    content # Strapi返回的原始Markdown内容
    images { # 关联的图片字段
      localFile {
        childImageSharp {
          gatsbyImageData(
            width: 800
            placeholder: BLURRED # 可选:添加模糊占位符
            formats: [AUTO, WEBP, AVIF] # 生成现代图片格式
          )
        }
        relativePath # 用于匹配Markdown中的图片路径
      }
    }
  }
}

3. 自定义gatsby-image渲染组件

写一个自定义组件,用来替换react-markdown默认的图片渲染逻辑。这个组件会把Markdown里的图片路径和我们从Strapi拉取的图片节点做匹配,然后用GatsbyImage渲染优化后的图片:

import { GatsbyImage, getImage } from "gatsby-plugin-image";

const StrapiMarkdownImage = ({ src, alt, ...props }) => {
  // 提取Markdown图片路径中的文件名(比如从"/uploads/photo_abc.jpg"得到"photo_abc.jpg")
  const imageFilename = src.split("/").pop();
  
  // 从传入的图片数组中找到匹配的图片节点
  const matchedImage = props.images.find(img => 
    img.localFile.relativePath.includes(imageFilename)
  );

  // 如果找不到匹配的图片(比如外部链接图片),则渲染普通img作为降级
  if (!matchedImage) {
    return <img src={src} alt={alt || ""} {...props} />;
  }

  const optimizedImage = getImage(matchedImage.localFile.childImageSharp);
  return <GatsbyImage image={optimizedImage} alt={alt || ""} {...props} />;
};

4. 在react-markdown中使用自定义渲染器

最后,在渲染Markdown内容时,通过renderers属性替换默认的图片渲染器,把我们的自定义组件传进去:

import ReactMarkdown from "react-markdown";

const PostPage = ({ data }) => {
  const post = data.strapiPost;

  return (
    <article className="post-content">
      <h1>{post.title}</h1>
      <ReactMarkdown
        children={post.content}
        renderers={{
          // 用自定义组件替换默认的图片渲染
          image: (imageProps) => (
            <StrapiMarkdownImage {...imageProps} images={post.images} />
          )
        }}
      />
    </article>
  );
};

export default PostPage;

注意事项

  • 确保Strapi中Markdown里的图片路径是Strapi上传后的路径(比如/uploads/xxx.jpg),这样才能和localFile的relativePath匹配上。
  • 如果你的Strapi使用了云存储(比如Cloudinary),需要确保gatsby-source-strapi能正确拉取到云存储的图片文件,或者调整匹配逻辑来对应云存储的URL。
  • 对于外部链接的图片,这个方案会自动降级为普通img标签,因为gatsby-image无法处理外部图片。

内容的提问来源于stack exchange,提问作者Serhii Zharkov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:22:33