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

