盖茨比在graphql查询返回后获取图像路径

IT技术 reactjs graphql gatsby
2022-08-03 23:34:57

所以我在 Gatsby and Remark 中写了一个博客站点。我的帖子结构是这样的:

Library/
 -- category-name/
 ---- article-name/
 ------ index.md

这非常有效,并导致我能够制作类似/category-name/article-name.

我还想做的是能够在其中放置一个名为“hero.jpg”的图像,并让 Gatsby 自动拾取它,而无需添加对它的 frontmatter 引用。

通过将以下内容添加到“gatsby-node.js”中,我已经设法做到了这一点:

const hero = (fs.existsSync(path.resolve(__dirname, `src/library/pages/${slug}hero.jpg`))) ? `${slug}hero.jpg` : ''
createNodeField({
      node,
      name: 'hero',
      value: hero,
    })

就graphql数据而言,这有效,我现在看到以下内容:

{
  "node": {
  "id": "3190922a-2207-5621-a7be-e02be9e8da24",
  "fields": {
    "hero": "/category-name/article-name/hero.jpg"
  },
},

但是在实际页面上,图像链接/category-name/article-name/hero.jpg不存在,所以我得到一个死图像。我知道这是因为我的图像路径正在被转换,gatsby-transformer-sharp但我不知道如何计算出它正在被转换成什么。

我相信我需要做一些类似于这个 SO question的答案的事情,但这似乎希望您知道relativePath在您编写查询时是,但在查询返回第一个之前我不会有这些信息时间。

为清晰起见添加了 OnCreateNode 钩子


exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions
  // Add slug to MarkdownRemark node
  if (node.internal.type === 'MarkdownRemark') {
    const slug = createFilePath({ node, getNode, basePath: 'library' })
    const hero = (fs.existsSync(path.resolve(__dirname, `src/library/pages/${slug}hero.jpg`))) ? './hero.jpg' : ''

    createNodeField({
      node,
      name: 'slug',
      value: slug,
    })
    createNodeField({
      node,
      name: 'hero',
      value: hero,
    })
  }
}
1个回答

我意识到我之前的答案不正确且过于复杂(它依赖于节点创建顺序,也无需向 imageSharp 节点添加字段。如果有人感兴趣,请点击此处的链接。)。这是更好的答案:

用mardown查询hero同文件夹中的名字图片

由于主图总是和markdown文件在同一个目录,我们可以简单地根据它的目录来查询它。

            dir              name  ext
┌────────────┴────────────┐ ┌─┴─┐ ┌─┴─┐
absolute/path/to/directory/ hero  .png
absolute/path/to/directory/ index .md

Graphql 查询:

file ( dir: { eq: "absolute/path/to/directory" }, name: { "hero" } ) {
  childImageSharp {
    fixed {
      src
    }
  }
}

您需要对其进行的唯一修改gatsby-node.js是将此dir字段添加到您的页面中context,以便我们可以将其用作变量。我们可以dir通过做得到path.parse(node.fileAbsolutePath).dir,或者dir从remark的父节点获取字段getNode(node.parent.id).dir

   +  const { dir } = getNode(node.parent.id)

      createPage({
        path: node.fields.slug,
        component,
        context: {
   +      dir,
          slug: node.fields.slug,
        },
      })

并像这样查询它:

    export const pageQuery = graphql`
   -  query ArticleByPath($slug: String!) {
   +  query ArticleByPath($slug: String!, $dir: String!) {
        markdownRemark(fields: { slug: { eq: $slug } }) {
          id
          htmlAst
          frontmatter {
            title
          }
        }
   +    file (dir: { eq: $dir }, name: { eq: "hero" }) {
   +      childImageSharp {
   +        fixed {
   +          src
   +        }
   +      }
   +    }
      }
    `

并使用它:

    export default function Template({ data }) {
      const post = data.markdownRemark
  +   const hero = data.file ? data.file.childImageSharp : null
      return (
        <div className="landing-page-container">
          <Helmet title={`Your Blog Name - ${post.frontmatter.title}`} />
          <div className="blog-post">
  +         {hero && <img src={hero.fixed.src} alt={post.frontmatter.title} />}
            <h1>{post.frontmatter.title}</h1>
            <div className="blog-post-content">{renderAst(post.htmlAst)}</div>
          </div>
        </div>
      )
    }

这是的要点article.jsgatsby-node.js