The Gatsby.js framework has some well known and loved utilities for image optimization, and also some new ones that make the user experience even better.
The Basics ("what is sharp?")
Sharp is probably used on almost every Gatsby site, but most developers (including myself at one point) don't quite understand what pieces are doing what. We're told from the beginning to include a few plugins with the word "sharp" in it, here is what they do.
Taken directly from the Gatsby.js docs site:
gatsby-source-filesystem
plugin allows you to query files with GraphQLgatsby-plugin-sharp
powers the connections between Sharp and Gatsby Pluginsgatsby-transformer-sharp
allows you to create multiples images of the right sizes and resolutions with a query
Here is what these plugins look like when implemented in the configuration file. (note: other important, but not relevant parts of the config are omitted from this code snippet for brevity).
gatsby-config.yml
module.exports = {
...
plugins: [
'gatsby-transformer-sharp',
'gatsby-plugin-sharp',
{
resolve: 'gatsby-source-filesystem',
options: {
path: `${__dirname}/content`,
name: 'resources',
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
...
],
};
GraphQL
The next part is making sure you actually use the plugins you have defined in the config. It may seem odd to mention this, but simply querying for the most obvious image properties will result in doing the optimizing work without any of the benefits.
For example, here is a common graphql
query example for simply including image URL. Pay special attention to the banner
property, which represents an image included in resource (in this case markdown source).
export const pageQuery = graphql`
query ResourceIndexQuery {
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
category
banner {
publicURL
}
}
fields {
slug
}
excerpt
}
}
}
}
`;
In the above code, we reasonably assume that to display the image on our site, we should extract the publicURL
from the field we have defined for our image. This displays the image, but does so at the original resolution.
To leverage the Sharp plugins we need to extract the image URL differently. See the changes below for the banner
field.
export const pageQuery = graphql`
query ResourceIndexQuery {
allMarkdownRemark(sort: { fields: [frontmatter___date], order: DESC }) {
totalCount
edges {
node {
id
frontmatter {
title
date(formatString: "DD MMMM, YYYY")
category
banner {
childImageSharp {
fluid(maxHeight: 500) {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
excerpt
}
}
}
}
`;
We are now replacing publicURL
with
childImageSharp {
fluid(maxHeight: 500) {
...GatsbyImageSharpFluid
}
}
Fluid
indicates that Gatsby.js will make a number of resolutions that can be used for various client window sizes. (fixed
is also an option)
We use the "spread" operator to make all the properties accessible of GatsbyImageSharpFluid
which is required to implement gatsby-image
below.
React Component
With sharp included
in the graphql, we can reference the needed URL with the src
property. (This would also require replacing ...GatsbyImageSharpFluid
with simply src
)
<img src={data.markdownRemark.frontmatter.banner.childImageSharp.fluid.src} />
Progressive image loading
But we can easily make a very cool enhancement to our site by including gatsby-image
. This plugin does NOT need to be included in the gatsby-config.js file, but it does need to be imported for your component.
import Img from 'gatsby-image';
Then, instead of using a traditional img
tag, use the imported component and pass it the fluid
property (no further specification needed beyond that).
<Img
fluid={node.frontmatter.banner.childImageSharp.fluid}
title="Banner Image"
/>
You can read more about this plugin here. But the big win is lazy / progressive image loading (like Facebook). A low-resolution version of the image is shown first and then updated with a full-resolution version later. It is a subtle change that really improves the user experience.
Need a fresh perspective on a tough project?
Let’s talk about how RDG can help.