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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:27:35