fabien0102 / gatsby-starter

Gatsby 2.0 starter with typescript and many cools dev tools
386 stars 99 forks source link

Help request - Adding images to pages #65

Closed i001962 closed 6 years ago

i001962 commented 6 years ago

I'm looking to add a few images to the home page plus others and would appreciate some guidance. Where is the best place to store images so the build picks them up?

Is the /data folder where we should put images? e.g. create a /data/images folders then use graphql to those into the page at build time?

I was reading this tutorial's 'Rendering the images to index.js' section and thought I may need to do something like that for homepage images. Am approaching this correctly?

One of these days I wont have to end every question by stating how new gatsby/react are to me.

Thanks, Kevin

fabien0102 commented 6 years ago

Hello @i001962

First of all, carefull my starter is not really up to date with the last version of gatsby! (so you can have some misalignment with the current official gatsby documentation).

You can find have some image insertion example into the blogpost page: The query: https://github.com/fabien0102/gatsby-starter/blob/master/src/pages/blog.tsx#L133

The usage into a react component: https://github.com/fabien0102/gatsby-starter/blob/master/src/pages/blog.tsx#L35

Logically, every images inside your project is parse by the gatby plugin here: https://github.com/fabien0102/gatsby-starter/blob/master/gatsby-config.js#L53

So you can have access to your image in multiple resolutions (thanks to sharp).

The "easier" way to understand what happen is to add an image in your project (where you want, the choice is on your side ;) ) and go to the graphQL playground tools (the url is on the console when you start the server). After you should have access to your image into allImageSharp (or something like this).

I will try to make you a better tutorial if needed ^^ I just have switched to a new computer so I'm trying to give you an idea my memories :wink:

But yes, the main idea is to use graphql to get your image, so you can use the responsiveResolution and all optimisations from the Sharp plugin.

i001962 commented 6 years ago

@fabien0102 that's super helpful. Thanks for the response. I invested a fair amount of time this weekend to figure out how the parts work together and am looking forward to deploying a site based on your starter. Using /___graphql?query= is huge time saver. Thanks again.

i001962 commented 6 years ago

@fabien0102 Looks like I do need a bit more in the way of an image insertion tutorial. If you wouldn't mind, please assume there are more than one image per page.

Here's how I was thinking about it and where I got stuck: 1 - Create images directory and add a few images - done ImageSharp will see those at build time. 2 - using the graphiql query figure out the graphql to select the images for the new page (let's call this 'products' and assume it's generated with plop. 3 - This query return the images I want to insert into the new products page

query ProductsPage {
  pageimages: allImageSharp(filter: {id: {regex: "/siteimages/"}}) {
    edges {
    node {
         id
        ... on ImageSharp {
          responsiveResolution(width: 1000, height: 600) {
            src
            srcSet
          }
        }
      }
    }
  }
}

Returns:

{
  "data": {
    "pageimages": {
      "edges": [
        {
          "node": {
            "id": "/Users/Admin/aws/gatsby1/gatsby-starter-CTY/data/siteimages/LaborRates.png absPath of file >> ImageSharp",
            "responsiveResolution": {
              "src": "/static/LaborRates-5f6e68bffcbed1be89ef06216f9d960d-536e4.png",
              "srcSet": "/static/LaborRates-5f6e68bffcbed1be89ef06216f9d960d-536e4.png 1x"
            }
          }
        },
        {
          "node": {
            "id": "/Users/Admin/aws/gatsby1/gatsby-starter-CTY/data/siteimages/ScenarioPlanning.png absPath of file >> ImageSharp",
            "responsiveResolution": {
              "src": "/static/ScenarioPlanning-ba0d253e43a3dee5750f2eb0a2c7e3ce-9d697.png",
              "srcSet": "/static/ScenarioPlanning-ba0d253e43a3dee5750f2eb0a2c7e3ce-9d697.png 1x"
            }
          }
        }
      ]
    }
  }
}

4 - Here's the first place I get thrown off as your example is using then MarkdownRemarkConnection and I'm not. Can we just use this?

import { ImageSharp } from "../graphql-types";

I'm trying to modify your line of code but I can't quite figure this out as there is no 'frontmatter' equivelant in this case. I see what needs to be done I just don't know how to get there.

        **const cover = get(frontmatter, "image.children.0.responsiveResolution", {});**

Any guidance would be appreciated.

i001962 commented 6 years ago

@fabien0102 sometimes just writing down the problem helps me solve it.

Here's what I did to get it to work. I'm stilling trying to figure out the best practice (if you will) for multiple pages and multiple images per page but... I'm unstuck for now.

import { ImageSharp } from "../graphql-types";

...

const pageimages = props.data.pageimages.edges;
    console.log(pageimages[0].node.responsiveResolution.src);
    const cover = pageimages[0].node.responsiveResolution as ImageSharp;

...

<img src={cover.src} height="618" width="1000"></img>
fabien0102 commented 6 years ago

@i001962 If you have a specific semantic for each images, you can separate your queries to give a name to each image.

Two seperate queries (not tested, but you should have the idea)

fragment ImageFragment on ImageSharp {
edges {
    node {
         id
        ... on ImageSharp {
          responsiveResolution(width: 1000, height: 600) {
            src
            srcSet
          }
        }
      }
    }
}

query ProductsPage {
  laborRateImg: ImageSharp(filter: {id: {regex: "/LaborRate/"}}) {
    ...ImageFragment
  }
  scenarioImg: ImageSharp(filter: {id: {regex: "/Scenario/"}}) {
    ...ImageFragment
  }
}

or you can build a little helper function to get your specific image (with your previous query)

const getImage = (images, name) => {
  /* find your image by name and return the good one */
  return {src: "", srcSet: ""}
}

Lastly, you need to use the srcset attribute like this <img src={cover.src} srcset={cover.srcSet} /> if you want to have all resolutions availables ;)

Regarding "good practices", just find your way to do this in your context (something simple to maintained and understand) and stick with it 😃

i001962 commented 6 years ago

@fabien0102 got it! The Two seperate queries approach is working nicely. Thanks for the generous reply and highlighting the missing srcset attribute. I’m making progress and starting to figure out more on my own so hopefully these questions turn into PRs before too long.

Next area for me is figureing out how to replicate the blog page/post functionality (with tagcards) to pull from csv instead of md. Almost got it!