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

