gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.22k stars 10.32k forks source link

image path is not being converted from string | gatsby-image & childImageSharp #22918

Closed ItzaMi closed 4 years ago

ItzaMi commented 4 years ago

I'm sorry for the short question but this is partially related to another issue I had ( here ) that couldn't get solved.

What I'm getting in my actual project (using graphQL) is that gatsby-image and childImageSharp seem to recognize my image path as a string and not as an actual file or image. I'm using YAMl to feed the info into my pages.

I created a small reproduction to demonstrate my problem.

It seems like there's no conversion on my childImageSharp from 'string' to an actual 'file/image'.

What might be wrong here?

jonniebigodes commented 4 years ago

@ItzaMi i've picked up on your issue and i've just cloned your repo. I'm going to take a look and report back as soon as i get a possible answer. Do you mind waiting a bit?

ItzaMi commented 4 years ago

@jonniebigodes , I appreciate it. If there's anything wrong in what I have, please let me know.

jonniebigodes commented 4 years ago

@ItzaMi i took a look at the repo and i think i have a solution for you. Below are the steps i took to triage this issue.

With that in mind i changed your `gatsby-config to the following (i'm just leaving in the plugins portion to keep the comment shorter):


    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/blog`,
        name: `blog`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/assets`,
        name: `assets`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/content/images`, // the images for the yaml files
        name: `Bikes`,
      },
    },
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 590,
            },
          },
          {
            resolve: `gatsby-remark-responsive-iframe`,
            options: {
              wrapperStyle: `margin-bottom: 1.0725rem`,
            },
          },
          `gatsby-remark-prismjs`,
          `gatsby-remark-copy-linked-files`,
          `gatsby-remark-smartypants`,
        ],
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        //trackingId: `ADD YOUR TRACKING ID HERE`,
      },
    },
  /*   `gatsby-plugin-feed`, */
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `Gatsby Starter Blog`,
        short_name: `GatsbyJS`,
        start_url: `/`,
        background_color: `#ffffff`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `content/assets/gatsby-icon.png`,
      },
    },
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
    // this (optional) plugin enables Progressive Web App + Offline functionality
    // To learn more, visit: https://gatsby.dev/offline
    // `gatsby-plugin-offline`,
  ],

As you can see i added a new entry to the plugins array to get the images that you have in the yaml file. As without this change if you issued a graphql query like for instance:

{
      allImageSharp {
        edges {
          node {
            fluid(maxWidth: 1000) {
              src
              srcSet
              originalName
              sizes
              aspectRatio
            }
          }
        }
      }
    }

Without the addition the only returned information would be to the rest of the images, minus the ones you want (i checked and it didn't).

Moving on

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.' imageHere: imageTwo.jpg

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.' imageHere: imageTwo.jpg

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.' imageHere: imageTwo.jpg


The key thing to take from this change, as you can see i removed everything from the image asides it's name. You'll see it come together shortly.

- Moved onto to your `gatsby-node.js` and i saw that you're using `js-yaml` to load the yaml data but technically you don't have any correlation between the yaml and the Gatsby data layer. With that Gatsby has no knowledge of how to fetch the required image information that you're suplying to the template file via the `context` special prop and also to be consumed by `gatsby-image` (you'll see it shortly), with this in mind i changed it to the following:
```js

/**
 * auxiliary function to fetch the images from the Gatsby data layer
 * @param {Array} gatsbyImages array of data incoming from the Gatsby data layer
 * @param {String} imageToGet the name of the image to be fetched (all the data required)
 * @returns {Object} returns the corresponding node
 */
const fetchImageInformation = (gatsbyImages, imageToGet) => {
  const result = gatsbyImages.find(
    image => image.node.fluid.originalName === imageToGet
  )
  return result.node
}
exports.createPages = async ({ graphql, actions, reporter }) => {
  const { createPage } = actions
  const ymlDoc = yaml.safeLoad(
    fs.readFileSync("./src/content/projectPage/projectPage_v1.yaml", "utf-8")
  )
  const allImagesInfo = await graphql(`
    {
      allImageSharp {
        edges {
          node {
            fluid(maxWidth: 1000) {
              src
              srcSet
              originalName
              sizes
              aspectRatio
            }
          }
        }
      }
    }
  `)

  if (allImagesInfo.errors) {
    reporter.panicOnBuild(`Error while running GraphQL query.`)
    return
  }

  const { data } = allImagesInfo
  const { allImageSharp } = data
  const { edges } = allImageSharp

  const pageInformation = ymlDoc.map(element => {
    return {
      ...element,
      intro: {
        ...element.intro,
        introImage: fetchImageInformation(edges, element.intro.introImage),
      },
      sections: element.sections.map(sectionElement => {
        return {
          ...sectionElement,
          imageHere: fetchImageInformation(edges, sectionElement.imageHere),
        }
      }),
    }
  })
  /* ymlDoc.forEach(element => {
    console.log(JSON.stringify(element, null, 2))
    createPage({
      path: element.path,
      component: require.resolve("./src/templates/project-page.js"),
      context: {
        intro: element.intro,
        sections: element.sections
      },
    })
  }) */

  pageInformation.forEach(element => {
    createPage({
      path: element.path,
      component: require.resolve("./src/templates/project-page.js"),
      context: {
        intro: element.intro,
        sections: element.sections,
      },
    })
  })
}

Key thing to take from this, i added the grapqhl query to get the image information that gatsby-image consumes, (it could be fine tuned better, but for our purposes it will suffice) and also introduced a auxiliary function called fetchImageInformation this function will return the image information needed based on the image's name. And based on that it it will generate the pages you want with the information you need.

We're halfway through. Now time for the components.

const IntroSection = ({ title, introImage }) => {
  return (
    <Wrapper>
      <Title>{title}</Title>
      {/* <Img fluid={introImage.childImageSharp.fluid} /> */}
      <Img fluid={introImage.fluid} />
    </Wrapper>
  )
}

IntroSection.propTypes = {
  title: PropTypes.string,
}

export default IntroSection

Nothing too much done, just updated the fluid prop.


const Sections = ({ sections }) => (
  <Wrapper>
    {sections.map((section, i) => (
      <SubWrapper key={i}>
        <LeftSide>
          <Title>{section.title}</Title>
        </LeftSide>
        <RightSide>
          {section.description.map((item, i) => (
            <StyledDescription key={i}>{item}</StyledDescription>
          ))}
          {/* <Img fluid={section.imageHere.childImageSharp.fluid} /> */}
          <Img fluid={section.imageHere.fluid} />
        </RightSide>
      </SubWrapper>
    ))}
  </Wrapper>
)

export default Sections

Once again nothing too much to be done here, asides from the adjustment to the fluid prop.

Your template (src\templates\project-page.js) wasn't touched as you can see:

import React from "react"
import styled from "styled-components"

/* import YAMLData from "../content/projectPage/projectPage.yaml" */

import Sections from "../components/ProjectPage/Sections"
import IntroSection from "../components/ProjectPage/IntroSection"

const Wrapper = styled.article``

const ProjectPage = props => {
  const { pageContext } = props
  const { intro, sections } = pageContext

  return (
    <div>
      <Wrapper>
        <div>
          <IntroSection title={intro.title} introImage={intro.introImage} />
           <Sections sections={sections} />
        </div>
      </Wrapper>
    </div>
  )
}

export default ProjectPage

Almost there, two small tweaks and we're done.

import React from "react"
import { useStaticQuery,graphql,Link} from 'gatsby'
import Img from "gatsby-image"

/* import YAMLData from "../../content/projectPage/projectPage.yaml" */
import YAMLData from "../content/projectPage/projectPage_v1.yaml"
const Homepage = () => {
  const allimagesData= useStaticQuery(graphql`
  {
    allImageSharp {
      edges {
        node {
          fluid(maxWidth: 1000) {
            ...GatsbyImageSharpFluid
            originalName
          }
        }
      }
    }
  }
  `)
  const {allImageSharp}= allimagesData
  const {edges}= allImageSharp
  return (
    <div>
      {
        YAMLData.map((element,index)=>{
          const postImage= edges.find(infoImage=>infoImage.node.fluid.originalName===element.intro.introImage)
          return(
            <div key={`data_${index}`}>
              <h1>{element.intro.title}</h1>
              <Img fluid={postImage.node.fluid} alt={element.intro.imageAlt}/>
              <Link to={element.path}>{element.intro.title}</Link>
            </div>
          )
        })
      }
    </div>
  )
}

export default Homepage

The key thing to take from this, The yaml file is being loaded from the right place and once you load the page it will show the actual content, once again taking in as a source of thruth the yaml file.

As i wanted to see how this would behave i added the following to the yaml file:


# section 3
- path: showcase/showcase3
  intro:
    title: Showcase item 3
    introImage: imageThree.jpg
    imageAlt: Some Alt text for the cover image
  sections:
    - title: Section 1
      description:
        - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec dolor nec purus tincidunt consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc ultrices laoreet felis. Pellentesque tempor ex non urna varius, eu facilisis risus mattis. Cras et nibh in nisl facilisis tincidunt at finibus nisi. Duis ut placerat quam. Quisque aliquet ante in tellus pulvinar venenatis. Duis lacinia venenatis venenatis. Suspendisse eget luctus felis. Phasellus arcu justo, tempus quis commodo tristique, sagittis sed lectus. Morbi rhoncus id leo ut lacinia. Quisque elementum finibus nunc. Pellentesque hendrerit faucibus ex eu imperdiet. Quisque laoreet elit vel augue laoreet, ut finibus augue tincidunt. Morbi vel massa ut justo facilisis ornare sed vitae urna.

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.'
      imageHere: imageFour.jpg
    - title: Section 2
      description:
        - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec dolor nec purus tincidunt consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc ultrices laoreet felis. Pellentesque tempor ex non urna varius, eu facilisis risus mattis. Cras et nibh in nisl facilisis tincidunt at finibus nisi. Duis ut placerat quam. Quisque aliquet ante in tellus pulvinar venenatis. Duis lacinia venenatis venenatis. Suspendisse eget luctus felis. Phasellus arcu justo, tempus quis commodo tristique, sagittis sed lectus. Morbi rhoncus id leo ut lacinia. Quisque elementum finibus nunc. Pellentesque hendrerit faucibus ex eu imperdiet. Quisque laoreet elit vel augue laoreet, ut finibus augue tincidunt. Morbi vel massa ut justo facilisis ornare sed vitae urna.

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.'
      imageHere: imageTwo.jpg
    - title: Section 3
      description:
        - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec dolor nec purus tincidunt consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc ultrices laoreet felis. Pellentesque tempor ex non urna varius, eu facilisis risus mattis. Cras et nibh in nisl facilisis tincidunt at finibus nisi. Duis ut placerat quam. Quisque aliquet ante in tellus pulvinar venenatis. Duis lacinia venenatis venenatis. Suspendisse eget luctus felis. Phasellus arcu justo, tempus quis commodo tristique, sagittis sed lectus. Morbi rhoncus id leo ut lacinia. Quisque elementum finibus nunc. Pellentesque hendrerit faucibus ex eu imperdiet. Quisque laoreet elit vel augue laoreet, ut finibus augue tincidunt. Morbi vel massa ut justo facilisis ornare sed vitae urna.

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.'
      imageHere: imageThree.jpg

## section 4
- path: showcase/showcase4
  intro:
    title: Showcase item 4
    introImage: imageFour.jpg
    imageAlt: Some Alt text for the cover image
  sections:
    - title: Another Section 1
      description:
        - 'Bork extremely cuuuuuute shooberino much ruin diet puggo smol, shibe long doggo maximum borkdrive fluffer. blop puggo what a nice floof. '
      imageHere: imageOne.jpg
    - title: Another Section 2
      description:
        - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec dolor nec purus tincidunt consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc ultrices laoreet felis. Pellentesque tempor ex non urna varius, eu facilisis risus mattis. Cras et nibh in nisl facilisis tincidunt at finibus nisi. Duis ut placerat quam. Quisque aliquet ante in tellus pulvinar venenatis. Duis lacinia venenatis venenatis. Suspendisse eget luctus felis. Phasellus arcu justo, tempus quis commodo tristique, sagittis sed lectus. Morbi rhoncus id leo ut lacinia. Quisque elementum finibus nunc. Pellentesque hendrerit faucibus ex eu imperdiet. Quisque laoreet elit vel augue laoreet, ut finibus augue tincidunt. Morbi vel massa ut justo facilisis ornare sed vitae urna.

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.'
      imageHere: imageTwo.jpg
    - title: Another Section 3
      description:
        - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec dolor nec purus tincidunt consectetur. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nunc ultrices laoreet felis. Pellentesque tempor ex non urna varius, eu facilisis risus mattis. Cras et nibh in nisl facilisis tincidunt at finibus nisi. Duis ut placerat quam. Quisque aliquet ante in tellus pulvinar venenatis. Duis lacinia venenatis venenatis. Suspendisse eget luctus felis. Phasellus arcu justo, tempus quis commodo tristique, sagittis sed lectus. Morbi rhoncus id leo ut lacinia. Quisque elementum finibus nunc. Pellentesque hendrerit faucibus ex eu imperdiet. Quisque laoreet elit vel augue laoreet, ut finibus augue tincidunt. Morbi vel massa ut justo facilisis ornare sed vitae urna.

Pellentesque justo mauris, mattis vitae tortor nec, rutrum placerat sapien. Nulla quis tellus malesuada, vestibulum nisl in, semper metus. Sed maximus porta erat, nec iaculis diam sollicitudin et. Aliquam fringilla mi quis orci consequat, vel tempor quam volutpat. Fusce mollis sodales erat, vitae accumsan neque fermentum sit amet. Donec fermentum id arcu ut dictum. Fusce a elit velit. Nam sit amet orci non eros vestibulum commodo. Phasellus velit felis, rhoncus id semper ut, elementum ut erat.'
      imageHere: imageThree.jpg
    - title: Another Section 4
      description:
        - 'Doggo ipsum maximum borkdrive long woofer wow very biscit boof super chub, borking doggo adorable doggo you are doing me the shock. Much ruin diet thicc shoob boof yapper, long water shoob adorable doggo h*ck. Borkdrive pupperino puggorino doing me a frighten blep, yapper fluffer h*ck heckin good boys and girls you are doing me a frighten, you are doing me the shock fat boi blep. Thicc wow very biscit what a nice floof aqua doggo doggorino you are doing me the shock, pupperino h*ck very jealous pupper.  Very jealous pupper heckin fluffer, you are doing me a frighten. Adorable doggo super chub corgo heck, blop noodle horse'
      imageHere: imageFour.jpg
    - title: Another Section 5
      description:
        - 'I am bekom fat very taste wow floofs the neighborhood pupper pupper, very hand that feed shibe lotsa pats adorable doggo. Heckin angery woofer dat tungg tho sub woofer very hand that feed shibe dat tungg tho, long woofer tungg.'
      imageHere: imageFive.jpg
    - title: Another Section 6
      description:
        - 'Super chub blop corgo, adorable doggo. Blop the neighborhood pupper boof bork wow such tempt borkf fluffer, borking doggo very taste wow aqua doggo heckin angery woofer. Yapper you are doing me a frighten heckin angery woofer such treat bork the neighborhood pupper, super chub you are doing me the shock stop it fren. doge such treat.'
      imageHere: imageSix.jpg

The images added were copied over from a folder i usually use to triage issues that require some images.

ItzaMi_1

And:

ItzaMi_2

Clicking on a random page i'm presented with following:

ItzaMi_3

Sorry for the extremely long comment, but i wanted to clarify it as much as i can to give you the full picture.

Feel free to provide feedback so that we can close this issue or continue to work on it until we find a suitable solution

ItzaMi commented 4 years ago

@jonniebigodes IT WORKED! Thank you so much! In the reproduction repo it worked without any problems but I actually tried to implement it in the website it was breaking really badly since I was already using createPages for blog pages and other templates and I was return graphQL from that.

I ended up creating a const for that first graphQL call and used the one you suggested here as well and finished my gatsby-node with return Promise.all([regularGraphQL, pageInformation]);

After finishing this process I noticed that I had graphQL on my template project-page and if I maintained sections { title description imageHere { childImageSharp { fluid(maxWidth: 600) { base64 } } }

I would get an error saying Field "imageHere" must not have a selection since type "String" has no subfields. So I changed my graphQL to sections { title description imageHere }

I feel like, on the long run, this won't be very intuitive when it comes to code quality (since the other childImageSharp work properly) but at least we got this working.

When I exposed this problem on StackOverflow one of the replies said Oh sweet, that's typically what happens when Gatsby's inference system encounters a node that doesn't resolve cleanly to a file on the system. Even if it's just 1 and the other 999 work, the node is treated as a string type and I'm not sure if has anything to do with this issue that I presented.

Once again, thank you for your help and your time!

jonniebigodes commented 4 years ago

@ItzaMi no need to thank, glad that i was able to help with your issue!

Regarding the StackOverflow comment, i got to say this, as the data layer in Gatsby is a very powerfull one it doesn't come with his own issues, i mean that despite the fact that the team implemented a solid solution, there's always something that it's forgotten. And with a compreehensive documentation available there's always a case that slips through the cracks.

And in a way it's related to this issue and others that popped up.

The good thing is that this is a ever mutating framework and it's constantly being updated and optimized and with that the number of issues related to this keeps dropping systematically.

If you're ok with this feel free to close the issue when you're able.