Zápisník Josefa Rouska

Python a React.js programátor, zaměřený na Shopify integrace

Cool image loading with Gatsby.js v2 and Netlify CMS v2

Time has come and even I got the opportunity to try out currently trending Gatsby.js static site generator. The most popular feature, at least from my point of view, is Image Processing with gatsby-transformer-sharp. I thought “Everyone talks that I can have out of the box responsive images and other cool things!”. Yeah sure, but they didn’t use it together with Netlify CMS while using beta of v2 :)

Getting started with something as complex as Gatsby.js is always a challenge. Looking back I would compare Gatsby to Webpack. Complexity of plugin based processing pipeline makes it a bit harder to understand than good old static site generators.

Now let’s investigate what do we actually need to make this work. Here are the plugins we need.

gatsby-plugin-sharp

Exposes several image processing functions built on the Sharp.

gatsby-transformer-sharp

Makes it possible to query Sharp image processing library processed images using GraphQL.

gatsby-transformer-remark

Uses remark to parse the markdown files into usable data nodes for GraphQL.

gatsby-remark-images

This does the magic making images linked from markdown files responsive.

gatsby-remark-relative-images

This is where the fun begins! Gatsby assumes that images are colocated with posts. This approach doesn’t work with Netlify CMS, because it stores images in a single place. There’s issue with v2 which led me to make a slight change to fork which was addressing the issue.

I ended up with this configuration:

`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
    resolve: `gatsby-transformer-remark`,
    options: {
        plugins: [
            'gatsby-remark-relative-images',
            {
            resolve: `gatsby-remark-images`,
            options: {
                // It's important to specify the maxWidth (in pixels) of
                // the content container as this plugin uses this as the
                // base for generating different widths of each image.
                maxWidth: 930,
                backgroundColor: 'transparent', // required to display blurred image first
            },
        },
    ],
},

These are the versions that I’m using:

"gatsby-plugin-sharp": "next",
"gatsby-remark-images": "next",
"gatsby-transformer-remark": "next",
"gatsby-transformer-sharp": "next",
"gatsby-remark-relative-images": "git+https://github.com/stlk/gatsby-remark-relative-images.git",

When Gatsby is configured this way I can embed image in markdown file like this ![Chemex](/img/chemex.jpg) and get this awesome loading “blur up” behavior.

Working with images stored in frontmatter

The blog I was working on has image displayed in the blog post list. The cover image was defined in frontmatter as follows.

---
templateKey: blog-post
title: The ultimate Chemex guide
cover_image: /img/chemex.jpg

Then I needed to get back to the relative path issue. Because gatsby-remark-images only handles relative paths, it will happily ignore my cover_image. To fix it I had to convert path to relative. In gatsby-node.js we can hook in for onCreateNode callback. Keep in mind that this code works only with cover_image.

const mapNetlifyMediaPath = ({ node }) => {
  const { frontmatter } = node
  if (frontmatter) {
    const { cover_image } = frontmatter

    if (cover_image) {
      if (cover_image.indexOf('/img') === 0) {
        frontmatter.cover_image = path.relative(
          path.dirname(node.fileAbsolutePath),
          path.join(__dirname, '/static/', cover_image)
        )
      }
    }
  }
}

exports.onCreateNode = nodeContext => {
  mapNetlifyMediaPath(nodeContext)
}

With all important bits in place let’s try running gatsby develop, open http://localhost:8000/___graphql and run this query. You should see that image was processed.

{
  allMarkdownRemark {
    edges {
      node {
        frontmatter {
          title
          cover_image {
            childImageSharp {
              fluid(maxWidth: 700) {
                src
              }
            }
          }
        }
      }
    }
  }
}

On index.js page, I can then use this GraphQL query combined with gatsby-image package. This package provides wrapper around img tag to generate HTML required to display responsive images. GatsbyImageSharpFluid is a fragment provided by gatsby-image its result we will then pass to Img component.

cover_image {
    childImageSharp {
        fluid(maxWidth: 630) {
            ...GatsbyImageSharpFluid
        }
    }
}
import Img from 'gatsby-image'

<Img fluid={post.frontmatter.cover_image.childImageSharp.fluid} />

You can see entire component and website on GitHub.

Overall I like Gatsby. I it’s one of the two static site generators I enjoy using. The other being Jekyll.