DEV Community

Hunter Chang
Hunter Chang

Posted on • Edited on • Originally published at codebushi.com

An Introduction To Using Gatsby Image & Gatsby.js V2

This post was originally published at codebushi.com
For a video tutorial, check out https://www.youtube.com/watch?v=kOrohVsq_kI

Gatsby Image

Gatsby.js V2 was recently launched and there have been a few small changes to how Gatsby Image is implemented. Gatsby Image is a React component that makes it easy to optimize all the images on your website. It will resize images for you, so you don't load huge images on a mobile device, and it will also lazy load your images with a cool "blur-up" effect so that your initial page loads are blazing fast. If you're new to Gatsby, I highly recommend going through their official tutorial first and familiarize yourself with how Gatsby works.

Adding Gatsby Image to your static website can be a bit tricky, especially since Gatsby uses GraphQL to query and load your images before they can be used. Here's a breakdown of the steps needed:

1) Install the required npm packages and configure your gatsby-config.js settings.

2) Test that you can query for your images using GraphQL.

3) Choose which image type you will need, fixed or fluid, and add the query to your page.

4) Use Gatsby Image <Img> tags on your page.

Here's a demo of the final product:

Gatsby Image Demo ( view source )

Installing & Configuring Gatsby Image

We'll start off by installing the default Gatsby Starter. You can clone the repo or use the Gatsby CLI to install the starter.

gatsby new image-demo https://github.com/gatsbyjs/gatsby-starter-default
cd image-demo/
Enter fullscreen mode Exit fullscreen mode

If you used the CLI, you'll need to continue with yarn since the initial packages were installed with yarn and there will be a yarn.lock file. If you cloned the repo and used npm install, then continue to use npm so you don't mix the package installers. I'll be using yarn for the rest of this demo.

Install Gatsby Image

yarn add gatsby-image
Enter fullscreen mode Exit fullscreen mode

We'll also need three other packages, gatsby-transformer-sharp, gatsby-plugin-sharp, and gatsby-source-filesystem. If you are not using the default starter and already have these packages installed, you can skip this step.

yarn add gatsby-transformer-sharp gatsby-plugin-sharp gatsby-source-filesystem
Enter fullscreen mode Exit fullscreen mode

The gatsby-source-filesystem package allows Gatsby to use GraphQL on the images in a certain directory and make queries out of them. The two sharp plugins are what processes the images before you display them.

Open up your gatsby-config.js and add the plugins to it. I'll add them right before the existing plugins. Your file should look like this:

module.exports = {
  siteMetadata: {
    title: 'Gatsby Default Starter',
  },
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/images`,
        name: 'images',
      },
    },
    'gatsby-transformer-sharp',
    'gatsby-plugin-sharp',
    'gatsby-plugin-react-helmet',
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: 'gatsby-starter-default',
        short_name: 'starter',
        start_url: '/',
        background_color: '#663399',
        theme_color: '#663399',
        display: 'minimal-ui',
        icon: 'src/images/gatsby-icon.png', // This path is relative to the root of the site.
      },
    },
    'gatsby-plugin-offline',
  ],
}

Enter fullscreen mode Exit fullscreen mode

Important: Make sure you specify the correct path to your images! The gatsby-source-filesystem will look in this folder to access your images. Since we're using the default starter, there's already a folder at /src/images so we'll use that. Get some images off of Unsplash and add them to that folder.

Testing An Image Query With GraphQL

With the plugins installed, we can fire up our site in dev mode.

gatsby develop
Enter fullscreen mode Exit fullscreen mode

Navigate to http://localhost:8000/ to see your site in dev mode. Now we'll play with the GraphiQL interface to understand how the image query works. Head to http://localhost:8000/___graphql to see the GraphiQL view of the site. Here we can test the different queries available to us. I've added 3 images to my /src/images folder and named them one.jpg two.jpg and three.jpg. To query for one.jpg I'll use this:

query {
  imageOne: file(relativePath: {eq: "one.jpg"}) {
    childImageSharp {
      fluid(maxWidth: 1000) {
        base64
        tracedSVG
        aspectRatio
        src
        srcSet
        srcWebp
        srcSetWebp
        sizes
        originalImg
        originalName
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

If you hit the play button, you should see data in the response column. This proves that Gatsby is able to find your image and process it.

Try changing file(relativePath: {eq: "one.jpg"}) to the other images in that folder, and make sure you see the data return.

Adding The GraphQL Query

We can now copy this query and use it in our homepage component. Open up src/pages/index.js. You'll need to import graphql from 'gatsby' as well as Img from 'gatsby-image'. We'll add the query to the page, the final result looks like this:

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

import Layout from '../components/layout'

const IndexPage = (props) => (
  <Layout>
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

export default IndexPage

export const pageQuery = graphql`
  query {
    imageOne: file(relativePath: { eq: "one.jpg" }) {
      childImageSharp {
        fluid(maxWidth: 1000) {
          ...GatsbyImageSharpFluid
        }
      }
    }
  }
`
Enter fullscreen mode Exit fullscreen mode

The query looks a bit different than before, we've removed all the fields inside fluid(maxWidth: 1000) {} and used ...GatsbyImageSharpFluid, which is a "query fragment". Due to some limitations, we were not able to play with ...GatsbyImageSharpFluid before in GraphiQL, but we can add it here. You can read more about the different fragments on the Gatsby Image Readme.

Important: Notice how the file(relativePath: { eq: "one.jpg" }) part remains the same, this is because the relativePath is not relative to index.js but rather the folder you specified earlier in gatsby-config.js and the gatsby-source-filesystem. There is no need to change anything about the relativePath.

Gatsby Image has two types of responsive images, fixed and fluid. This distinction will vary what your query looks like. A fixed query has a set width and height and is for supporting different screen resolutions. A fluid query has a max-width and sometimes a max-height, and will create multiple images for supporting different screen sizes. For the most part, I find myself using the fluid type since my images will vary depending on the size of the screen. If you want to use the fixed type or wish to learn more about the two, check out the Readme.

Using The Gatsby Image Component

So we have our query on the page, the GraphQL data can be accessed via props in our IndexPage component. The full path to the data is props.data.imageOne.childImageSharp.fluid. We can pass this into the <Img> component like so:

<Img fluid={props.data.imageOne.childImageSharp.fluid} />
Enter fullscreen mode Exit fullscreen mode

You can destructure this however you like, I'm using the full path for clarity. The image should now be displaying on your dev site! To get all three images, just copy and paste the imageOne blocks and rename to imageTwo and imageThree. You can call these whatever you want, just make sure it matches whatever you pass into the <Img /> component.

query {
  imageOne: file(relativePath: { eq: "one.jpg" }) {
    childImageSharp {
      fluid(maxWidth: 1000) {
        ...GatsbyImageSharpFluid
      }
    }
  }
  imageTwo: file(relativePath: { eq: "two.jpg" }) {
    childImageSharp {
      fluid(maxWidth: 1000) {
        ...GatsbyImageSharpFluid
      }
    }
  }
  imageThree: file(relativePath: { eq: "three.jpg" }) {
    childImageSharp {
      fluid(maxWidth: 1000) {
        ...GatsbyImageSharpFluid
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The components would look like this:

<Img fluid={props.data.imageOne.childImageSharp.fluid} />
<Img fluid={props.data.imageTwo.childImageSharp.fluid} />
<Img fluid={props.data.imageThree.childImageSharp.fluid} />
Enter fullscreen mode Exit fullscreen mode

We're repeating a lot of the same stuff inside that query, it can be cleaned up by making a custom fragment. Pull out the childImageSharp blocks and make a new fragment like so:

export const fluidImage = graphql`
fragment fluidImage on File {
  childImageSharp {
    fluid(maxWidth: 1000) {
      ...GatsbyImageSharpFluid
    }
  }
}
`;
Enter fullscreen mode Exit fullscreen mode

We can then replace the repeating code with this new fragment like so:

export const pageQuery = graphql`
  query {
    imageOne: file(relativePath: { eq: "one.jpg" }) {
      ...fluidImage
    }
    imageTwo: file(relativePath: { eq: "two.jpg" }) {
      ...fluidImage
    }
    imageThree: file(relativePath: { eq: "three.jpg" }) {
      ...fluidImage
    }
  }
`
Enter fullscreen mode Exit fullscreen mode

We'll now have all three images on our homepage! You can play around with the different Gatsby fragments for different loading effects. ...GatsbyImageSharpFluid will give the "blur up" effect, try ...GatsbyImageSharpFluid_tracedSVG for a different effect and experiment with fixed images.

Gatsby Image Demo ( view source )

Top comments (4)

Collapse
 
jpm1118 profile image
Jack McCormick

Excellent tutorial Hunter! Quick question, if you don't mind. Why does the pageQuery const need to be exported? Is this simply how Gatsby-image accesses the query? Thanks!

Collapse
 
changoman profile image
Hunter Chang

Yes, that's how the component is able to consume the GraphQL query. I think it needs to be exported because that's how Gatsby is able to process it during the build. Check out this page for more info: gatsbyjs.org/docs/page-query

Collapse
 
mcborreo profile image
Caye

Hallo, thank you so much for this helpful guide! The DRY code at the end was a gem. If you don't mind asking me though, would you happen to know how to test a component that uses gatsby-image?

Collapse
 
twiloportium profile image
george.yiangou@me.com

This is a good learning curve to get going with graphql and gatsby-image. Nicely structured.