Gatsby Source Contentful 4.x 技术问题:Rich Text无法获取图片与超链接
解决Contentful Rich Text变更后无法获取图片与超链接的问题
看起来你遇到的问题是Contentful近期的API变更导致Rich Text里的嵌入式资源(图片)和条目超链接无法正确映射到Gatsby应用中。我帮你分析下问题根源并给出具体修复方案:
问题核心
Contentful的Rich Text结构更新后,嵌入式资源和条目超链接不再直接把完整数据塞进node的data字段里,而是只保留目标资源的ID,实际的资源数据需要从references数组中匹配获取。你当前的代码没有处理这个ID匹配逻辑,所以打印出来的data或node内容才会为空。
修复步骤
1. 确保依赖版本兼容
首先把gatsby-source-contentful升级到最新版本,旧版本大概率没适配Contentful的新变更:
npm update gatsby-source-contentful
2. 修正GraphQL查询
你的查询只获取了Asset类型的引用,还得加上Entry类型的引用(对应ENTRY_HYPERLINK),同时保证引用字段完整:
export const pageQuery = graphql` query MyQuery { allContentfulBlogPost { nodes { bodyRichText { raw references { ... on ContentfulAsset { contentful_id fluid(maxWidth: 600) { ...GatsbyContentfulFluid_withWebp } title description } ... on ContentfulBlogPost { # 替换成你实际的Entry类型,比如页面、产品等 contentful_id slug # 假设你的Entry用slug做路由标识 title } } } } } } `;
3. 调整Rich Text渲染逻辑
修改options里的renderNode函数,通过资源ID从references数组中匹配对应的完整资源数据:
import React from 'react'; import { graphql, Link } from 'gatsby'; import Img from 'gatsby-image'; import { renderRichText } from 'gatsby-source-contentful/rich-text'; import { BLOCKS, MARKS, INLINES } from '@contentful/rich-text-types'; const Bold = ({ children }) => <span className="bold">{children}</span>; const Text = ({ children }) => <p className="align-center">{children}</p>; function privacy({ data }) { const post = data.allContentfulBlogPost.nodes[0]; const description = post.bodyRichText; // 把references转成键值对,方便通过ID快速查找资源 const referenceMap = description.references.reduce((map, ref) => { map[ref.contentful_id] = ref; return map; }, {}); const options = { renderMark: { [MARKS.BOLD]: (text) => <Bold>{text}</Bold> }, renderNode: { [INLINES.ENTRY_HYPERLINK]: ({ data }) => { const linkedEntry = referenceMap[data.target.sys.id]; if (!linkedEntry) return null; // 根据你的Entry结构调整路由,这里用slug做示例 return <Link to={`/${linkedEntry.slug}`}>{linkedEntry.title}</Link>; }, [BLOCKS.PARAGRAPH]: (node, children) => <Text>{children}</Text>, [BLOCKS.EMBEDDED_ASSET]: ({ data }) => { const asset = referenceMap[data.target.sys.id]; if (!asset?.fluid) return null; return <Img fluid={asset.fluid} alt={asset.title || asset.description || '图片'} />; } } }; return <div>{description && renderRichText(description, options)}</div>; } export default privacy;
关键说明
- 我们通过
referenceMap把references数组转换成以contentful_id为键的对象,这样能快速通过node里的目标ID找到完整资源数据。 - 对于
ENTRY_HYPERLINK,要根据你实际的Entry类型(比如ContentfulPage、ContentfulProduct)调整查询字段和路由逻辑。 - 对于
EMBEDDED_ASSET,确保你获取了fluid(或fixed)字段,这样Gatsby Image组件才能正常渲染图片。
这样修改后,你应该就能正确获取到图片和超链接的资源数据了。
内容的提问来源于stack exchange,提问作者Jegs
相关产品推荐
相关产品推荐

