Upgrading to Gatsby 3


Gatsby 3 has a major change: all image-related syntax has changed. If an existing project upgrades to Gatsby 3 without updating the image syntax, it might work fine, or it might break, or show some errors. Because my project had some strange errors, I decided to upgrade my blog’s image syntax. This is what they call “better safe than sorry,” right?

Photo by Rodolfo Clix from Pexels

Plugin upgrade

Gatsby 2 used gatsby-image for image plugins. When upgrading, you can first remove it and switch to gatsby-plugin-image, along with upgrading image-related plugins:

    npm uninstall gatsby-image
    npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp

In Gatsby 2, whether static or dynamic images, you would import the Img component from import Img from 'gatsby-image' at the top of the file to set up images.

Gatsby 3 changes this: static images import import { StaticImage } from "gatsby-plugin-image", and dynamic images import import { GatsbyImage } from "gatsby-plugin-image".

Advantages

Why upgrade to Gatsby 3? Why does Gatsby 3 require new syntax for images? I personally think the new syntax has two advantages:

  1. In Gatsby 2, static images all needed to be provided through GraphQL. Gatsby 3’s new syntax uses the StaticImage component, which allows you to put a URL or relative path directly into the property, which is indeed much more convenient.
  2. In Gatsby 2, dynamic images required setting some options in both GraphQL and component properties. Now you only need to set them in GraphQL, which makes the syntax a bit cleaner.

Static images

When upgrading static images, you need to pay attention to the following points:

  1. Static images <StaticImage /> no longer need to get data from GraphQL.
  2. Using a component like <StaticImage src="trex.png" width={width} height={width/2} /> is almost the same as HTML’s <img />.
  3. <StaticImage /> still enjoys Gatsby’s lazy loading, automatic generation of appropriately sized images, and other features.
  4. If remote files change, they won’t automatically update immediately; they’ll update after a rebuild.
  5. In Gatsby’s documentation, for the options section, choose the string parts, not the enum.
  6. <StaticImage /> props cannot be passed from other files, functions, or components.

My images come from a CMS and are often passed through properties, so I don’t actually use <StaticImage /> very often; I use <GatsbyImage /> more.

Dynamic images

The syntax for dynamic images has changed quite a bit. One major point is the syntax in GraphQL:

    fixed {
        ...GatsbyImageSharpFixed
    }

Changed to:

    gatsbyImageData(layout: FIXED)

Or:

    gatsbyImageData(
        width: 200
        placeholder: BLURRED
        formats: [AUTO, WEBP, AVIF]
    )

The component syntax becomes: <GatsbyImage image={data.file.childImageSharp.gatsbyImageData} />

We can observe that the options that were in the component in Gatsby 2 have all been moved to GraphQL. In Gatsby 3, the component doesn’t need to set any properties.

Note that the official Gatsby documentation lists option values: use uppercase enum values for GraphQL, lowercase for component properties.

Other methods

getImage()

To use this method, you can import it at the top of the file: import { getImage } from 'gatsby-plugin-image'. This method’s main function is that data.file.childImageSharp.gatsbyImageData in <GatsbyImage image={data.file.childImageSharp.gatsbyImageData} /> can be replaced with getImage(data.file.childImageSharp).

Using this syntax, if the value of gatsbyImageData is null, getImage() will return undefined instead of crashing the entire app. It’s essentially the same as the childImageSharp?.gatsbyImageData syntax, so you don’t have to use getImage() if you don’t want to.

getSrc()

Similar to getImage(), mainly used when you don’t need Gatsby’s image processing features and just need to get the image URL directly, for components like SEO. The purpose is also to prevent null errors.

    import { getSrc } from "gatsby-plugin-image"
    const HomePage = ({ data }) => {
        const imagePath = getSrc(data.file)
        return (
            <>
                <SEO imageSrc={imagePath} />
            </>
        )
    }

Examples

You can click “Before” and “After” to see the original files:

Before:

            images {
              fluid {
                ...GatsbyContentfulFluid
              }

After:

    images {
        gatsbyImageData(
            width: 800
            placeholder: BLURRED
            aspectRatio:1.5
        )
    }

Before:

    <TagCard
        slug={slug.toLowerCase()}
        key={`tag-${slug.toLowerCase()}`}
        iceFireNumber={iceFireNumber}
        postTitle={title}
        publishedDate={publishedDate}
        excerpt={excerpt}
        timeToRead={(timeToRead * 1.5)}
        imageSrc={element.images[0].fluid}
    />

After:


    const image = getImage(element.images[0]);
    return (
    <TagCard
        slug={slug.toLowerCase()}
        key={`tag-${slug.toLowerCase()}`}
        iceFireNumber={iceFireNumber}
        postTitle={title}
        publishedDate={publishedDate}
        excerpt={excerpt}
        timeToRead={(timeToRead * 1.5)}
        image={image}
    />

Before:

    import Img from 'gatsby-image'

After:

    import { GatsbyImage } from 'gatsby-plugin-image'

Before:

    <Link to={`/blog/${slug}/`}>
        <Img className="db" fluid={{ ...imageSrc, aspectRatio: 1.5 }} />
    </Link>

After:

    <Link to={`/blog/${slug}/`}>
        <GatsbyImage className="db" image={image} alt={postTitle} />
    </Link>

How to read documentation

For detailed upgrade steps, refer to the high-quality official documentation. The above is just my summary and additions of what I think are the most important points. Next, I’ll share some insights from this upgrade experience.

As a Gatsby developer, you inevitably need to read Gatsby documentation frequently. In fact, Gatsby’s documentation quality is excellent, not to mention the useful example code, and some places even include video tutorials. Despite this, I always felt that reading Gatsby documentation took a lot of time.

My previous way of reading documentation was to read while doing: first understand the documentation, then follow step by step, jumping to other documentation or Googling information in between, then writing code to implement, then going back to the documentation to continue implementation, and finally taking notes after successfully implementing.

This process had a small drawback: when I went back to check the documentation halfway through, I found it very time-consuming for the following reasons:

  1. The documentation is in English, which is always slower to read than Chinese.
  2. The documentation is too detailed and covers various situations, but I might only need 2-3 scenarios.
  3. The documentation’s organization logic doesn’t necessarily match my search logic.

So for this Gatsby 3 upgrade, I made a small change: I read the documentation first without writing code, directly extracting the parts I thought I would use to create notes, essentially creating my own version of the documentation. Then when I started writing code, I followed my own version of the documentation.

I discovered that this small change significantly reduced the time I spent reading documentation, because I was reading my own Chinese version of the documentation, which only documented the 2-3 scenarios I would use. More importantly, this customized documentation followed my own logic for remembering and searching, so I could find things very quickly with my eyes.

There’s a small issue: because I wasn’t implementing while reading the documentation, I occasionally misunderstood the original documentation. That’s okay—when you discover this situation, just modify your own version of the documentation. And when the upgrade is complete, organizing notes will be much faster.

For this upgrade to Gatsby 3, this method of reading documentation was actually my biggest takeaway.