Гэтсби получает путь к изображению после того, как запрос GraphQl вернулся - PullRequest
0 голосов
/ 15 января 2019

Итак, я написал блог-сайт в Гэтсби и Ремарк. Я структурировал свои посты так:

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

Это сработало очень хорошо, и я смог создать такие пути, как /category-name/article-name.

То, что я также хотел бы сделать, это иметь возможность помещать туда изображение с именем hero.jpg и автоматически выбирать его для Гэтсби, не добавляя в него ссылку на 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, но я не знаю, как определить, во что он преобразуется.

Я считаю, что мне нужно сделать что-то похожее на ответы на на этот ТАК вопрос , но, похоже, вы ожидаете, что вы знаете, что 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 Ответ

0 голосов
/ 21 января 2019

Я понял, что мой предыдущий ответ был неправильным и чрезмерно сложным (он основан на порядке создания узлов, также нет необходимости добавлять поля к узлам imageSharp. Вот ссылка , если кому-то интересно.). Вот лучший ответ:

Запрос изображения hero имени в той же папке с мардаундом

Поскольку изображение героя всегда находится в том же каталоге, что и файл уценки, мы можем просто запросить его по его каталогу.

            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 из родительского узла примечания 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.js и gatsby-node.js.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...