Optimizing Page Load with Gatsby Image: Implementing Static and Dynamic Assets
Learn how to implement gatsby-plugin-image to reduce CLS and improve LCP by automating image resizing and modern format conversion during the build process.
10 Jul 2025, 10:18 UTC

The Performance Bottleneck: Unoptimized Images
Large, unoptimized images are a common cause of high Cumulative Layout Shift (CLS) and slow Largest Contentful Paint (LCP) in Gatsby sites. Without a structured image pipeline, browsers download full-resolution assets regardless of the user's screen size, wasting bandwidth and hurting Core Web Vitals scores.
The fix is a build-time processing pipeline that generates multiple resolutions and modern formats (WebP/AVIF) automatically. Using the gatsby-plugin-image ecosystem, the browser can reserve the correct space for an image before it loads, eliminating layout jumps.
Prerequisites
- A Gatsby project (v4.0 or newer recommended).
- A Node.js environment with sufficient memory — Sharp, the underlying processing library, is CPU and RAM intensive.
- Images stored locally in the
src/imagesdirectory, or remote images brought into the GraphQL layer via a source plugin.
Installing the Image Pipeline
Gatsby requires three plugins to transform raw files into optimized assets. Run this in your project root:
npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharpThen enable them in gatsby-config.js:
module.exports = {
plugins: [
`gatsby-plugin-image`,
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
],
}Run gatsby develop afterward and confirm the site starts without plugin resolution errors before proceeding.
Implementation Patterns
Scenario A: Fixed Assets with StaticImage
Use the StaticImage component for images that do not change based on data, such as logos or hero backgrounds. No GraphQL query is needed — the image is processed at build time from the file path.
import { StaticImage } from "gatsby-plugin-image"
export function Header() {
return (
<StaticImage
src="../images/logo.png"
alt="Company Logo"
placeholder="blurred"
width={200}
/>
)
}Note that src must be a static path resolvable at build time — dynamic variables are not supported.
Scenario B: Dynamic Assets with GatsbyImage
For images sourced from Markdown, a CMS, or JSON files, use the GatsbyImage component with a GraphQL query that defines the transformations (resizing, formats, placeholders).
Example GraphQL query:
export const query = graphql`
query {
file(relativePath: { eq: "blog-post-hero.jpg" }) {
childImageSharp {
gatsbyImageData(
width: 800
placeholder: BLURRED
formats: [AUTO, WEBP, AVIF]
)
}
}
}
`Rendering the result:
import { GatsbyImage, getImage } from "gatsby-plugin-image"
const BlogPost = ({ data }) => {
const image = getImage(data.file)
return <GatsbyImage image={image} alt="Blog Hero" />
}Comparison: StaticImage vs. GatsbyImage
| Feature | StaticImage | GatsbyImage |
|---|---|---|
| Data source | Local file path | GraphQL node |
| Query required | No | Yes |
| Typical use case | UI elements, logos | CMS content, galleries |
| Flexibility | Fixed at build time | Dynamic sizing and cropping |
Diagnostic Checks and Verification
After implementing, verify the pipeline with these checks:
- Inspect the DOM: Right-click the image and choose "Inspect". The
<img>tag should contain asrcsetattribute with multiple URLs, confirming Gatsby generated sizes for different screens. - Network analysis: In DevTools, open the Network tab, filter by "Img", and reload. The Type column should show
webporavifrather thanjpegorpngin supporting browsers. - Lighthouse audit: Run a Lighthouse report in Chrome and confirm the "Properly size images" and "Efficiently encode images" audits pass.
Also check that explicit width and height (or a fixed aspect ratio) are set; missing dimensions let the browser fail to reserve space, reintroducing CLS even with optimized files.
Build-Time Limitations and Risks
- Build duration: Processing hundreds of high-resolution images can significantly lengthen builds. If CI builds time out, reduce the number of generated formats or consider a remote image CDN.
- Memory exhaustion: Sharp can crash the Node process on low-memory machines. If you hit out-of-memory errors during builds, raise the Node heap limit, for example with
NODE_OPTIONS=--max-old-space-size=4096in your build environment. - Remote images:
StaticImagecannot load remote URLs. Remote assets must be pulled into the Gatsby GraphQL layer via a source plugin (such asgatsby-source-filesystemwith the appropriate remote-file configuration, or a CMS-specific plugin) and rendered withGatsbyImage.
Rollback Procedure
If the plugin causes build failures or unexpected layout behavior:
- Remove
gatsby-plugin-image,gatsby-plugin-sharp, andgatsby-transformer-sharpfromgatsby-config.js. - Replace
<GatsbyImage>and<StaticImage>components with standard HTML<img>tags. - Run
npm uninstall gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp, then rebuild to confirm the site compiles.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.