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

Gatsby中如何将Graph_pages节点与生成的Markdown及Image节点关联?

解决Graph_pages节点与生成的MarkdownNode、ImageAsset关联查询问题

你的代码已创建对应子节点,但关联查询失效主要有两个核心问题:一是MarkdownNode的contentDigest硬编码导致节点有效性异常,二是缺少显式关联字段辅助查询(尽管Gatsby会自动维护parent/children关联,但显式字段更可靠)。

修复步骤

1. 修正MarkdownNode的contentDigest

硬编码的contentDigest: 'contentDigest'会让Gatsby无法正确识别节点唯一性,需替换为基于实际内容生成的有效摘要:

const mdContent = he.decode(node["body"]);
const mdNode = {
  id: nodeId,
  parent: node.id,
  internal: {
    type: `MarkdownNode`,
    mediaType: "text/markdown",
    content: mdContent,
    contentDigest: createContentDigest(mdContent), // 用实际内容生成摘要
  },
};
createNode(mdNode);

2. 给Graph_pages节点添加显式关联字段

通过createNodeField给父节点添加指向子节点的ID字段,方便查询时直接关联:
在创建完两个子节点后,追加以下代码:

// 关联MarkdownNode
createNodeField({
  node,
  name: "markdownNodeId",
  value: nodeId,
});

// 关联ImageAsset
createNodeField({
  node,
  name: "imageAssetId",
  value: assetId,
});

3. 确保remark插件配置正确

在gatsby-config.js中确认已启用gatsby-transformer-remark,才能解析你的MarkdownNode:

module.exports = {
  plugins: [
    `gatsby-transformer-remark`,
    // 其他插件...
  ],
};

修改后的完整代码

export const onCreateNode: GatsbyNode["onCreateNode"] = async ({
  node,
  actions: { createNode, createNodeField },
  createNodeId,
  createContentDigest,
}) => {
  if (node.internal.type === "Graph_pages") {
    // 创建MarkdownNode
    const mdContent = he.decode(node["body"]);
    const nodeId = `MarkdownNode:${createNodeId(`${node.id}-body`)}`;
    const mdNode = {
      id: nodeId,
      parent: node.id,
      internal: {
        type: `MarkdownNode`,
        mediaType: "text/markdown",
        content: mdContent,
        contentDigest: createContentDigest(mdContent),
      },
    };
    createNode(mdNode);

    // 创建ImageAsset
    const pathname = new URL(node.image).pathname;
    const fileNameWithExtension = path.basename(pathname);
    const extension = path.extname(fileNameWithExtension);
    const fileNameWithoutExtension = path.basename(
      fileNameWithExtension,
      extension
    );
    const imageAttr = await probe(node.image);
    const imageData = {
      url: `https://XXXXX.netlify.app/.netlify/images?url=${node.image}`,
      placeholderUrl: `https://XXXXX.netlify.app/.netlify/images?url=${node.image}&w=%width%&h=%height%`,
      mimeType: imageAttr.mime,
      filename: fileNameWithoutExtension,
      width: imageAttr.width,
      height: imageAttr.height,
      alt: `Red and rosa infinity thingy floating in air`,
    };
    const assetId = `ImageAsset:${createNodeId(`${node.id}-image`)}`;
    createNode({
      ...imageData,
      id: assetId,
      parent: node.id,
      children: [],
      internal: {
        type: `ImageAsset`,
        contentDigest: createContentDigest(imageData),
      },
    });

    // 添加显式关联字段
    createNodeField({
      node,
      name: "markdownNodeId",
      value: nodeId,
    });
    createNodeField({
      node,
      name: "imageAssetId",
      value: assetId,
    });
  }
};

查询示例

方式1:通过Gatsby自动生成的child字段

query {
  allGraphPages {
    nodes {
      id
      childMarkdownNode {
        html # remark解析后的HTML内容
      }
      childImageAsset {
        url
        width
        height
        alt
      }
    }
  }
}

方式2:通过显式添加的字段关联

query {
  allGraphPages {
    nodes {
      fields {
        markdownNodeId
        imageAssetId
      }
    }
    markdownNodes: allMarkdownNode {
      nodes {
        id
        html
      }
    }
    imageAssets: allImageAsset {
      nodes {
        id
        url
        width
      }
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:56:16