Gatsby with WPGraphQL, ACF and Gatbsy-Image
Tags: gatsby, webdev, graphql, wpgraphql
Published: 2019-08-07 18:22:27

So, there is a lot happening around Gatsby with WordPress and WPGraphQL. At times, it can get confusing and a lot of given functionality is hard to find or figure out. I am working on a client project right now and somehow had to **handle images**, that I source through my WordPress backend.

After trying out all sorts of solutions and working through the plugin library of Gatsby, I ended up finding a little piece of documentation, that led me to a solution, that works for me. And, because some very helpful people in the **WPGraphQL Slack Chat** asked me to write about that solution ... here I am.

> I simply wanted to have my WordPress Media as static files inside my Gatsby app and work with the gatsby-image plugin for transformation/optimization.


## Libraries used
- [GatsbyJs](https://www.gatsbyjs.org/)
  - [gatsby-source-graphql](https://www.gatsbyjs.org/packages/gatsby-source-graphql)
  - [Gatsby-Image](https://www.gatsbyjs.org/packages/gatsby-image/)
     - [gatsby-source-filesystem](https://www.gatsbyjs.org/packages/gatsby-source-filesystem/)     
     - [gatsby-transformer-sharp](https://www.gatsbyjs.org/packages/gatsby-transformer-sharp)
     - [gatsby-plugin-sharp](https://www.gatsbyjs.org/packages/gatsby-plugin-sharp/)
- WordPress
  - [ACF](https://www.advancedcustomfields.com/)
  - [WPGraphQL](https://github.com/wp-graphql/wp-graphql) | [Docs](https://docs.wpgraphql.com/)
  - [WPGraphQL ACF](https://github.com/wp-graphql/wp-graphql-acf)

---

## Gatsby Config

```javascript
/* --------- gatsby-config.js --------- */

module.exports = {

  plugins: [

    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/assets/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
    {
      resolve: "gatsby-source-graphql",
      options: {
        typeName: "WPGraphQL",
        fieldName: "wpgraphql",
        url: `https://${YOUR_DOMAIN}/graphql`,
      },
    },
  ]
}

```

- Make sure all the plugins are mentioned correctly in your config file
- For some reason, it can cause errors not having `gatsby-source-filesystem` used in the configs. Make sure it resolves to a valid path, even if there are no images inside the folder.


---


## Gatsby Node

```javascript

/* --------- gatsby-node.js --------- */

const { createRemoteFileNode } = require(`gatsby-source-filesystem`)

exports.createResolvers = async (
  {
    actions,
    cache,
    createNodeId,
    createResolvers,
    store,
    reporter,
  },
) => {
  const { createNode } = actions

  await createResolvers({
    WPGraphQL_MediaItem: {
      imageFile: {
        type: "File",
        async resolve(source) {
          let sourceUrl = source.sourceUrl

          if (source.mediaItemUrl !== undefined) {
            sourceUrl = source.mediaItemUrl
          }

          return await createRemoteFileNode({
            url: encodeURI(sourceUrl),
            store,
            cache,
            createNode,
            createNodeId,
            reporter,
          })
        },
      },
    },
  })
}
```

That's really all you need. Let's break it down a little:
- `WPGraphQL_MediaItem`: This depends on your config. It starts with the `typeName` of your gatsby-source-graphql.
- [createRemoteFileNode](https://www.gatsbyjs.org/packages/gatsby-source-filesystem/#createremotefilenode) gives you the ability to pull in remote files and automatically adds them to your schema.
- `imageFile`: will be the type you can query (see below).
- `type: 'File'`: will add the MediaItems as Files, which is great, because now gatsby-image can make use of it.
- `url: encodeURI(sourceUrl)`: Here we encode the Url coming from WordPress, to make sure it is parsed correctly even if the image paths include umlauts.


## Pages Query
```graphql

# page.js

query {
  WPGraphQL {
    pages {
      nodes {
        featuredImage {
          sourceUrl
          imageFile {
            childImageSharp {
              fixed {
              ...GatsbyImageSharpFixed
              }
            }
          }
        }
      }
    }
  }
}
```

**Important:** Always query `sourceUrl`, otherwise it doesn't work, because the resolver would miss that data.

## Final thoughts

Thats all there is to it. And it works with ACF Media files too. Same same.

Almost ... I think it is important to mention, that with this method all available Media-Files coming from WordPress will be pulled in the cache. So, if there is, for some reason, a clear of the cache happening, it would need to pull them in again I guess. For performance, it could still be more useful to somehow fetch all the Media-Files apart from the Gatbsy-Cache. That would mean though, you have to do the hard work of creating the schema yourself. I'm sure there will be great solutions for that too. Would be happy if someone has some experience with that and would share their thoughts :)

## Caching

If your server doesn't support etags, the default caching of the `gatsby-source-filsystem` won't work.

You can checkout the custom solution by Robert Marshall here, which should be slightly faster and doesn't rely on etags: https://thoughtsandstuff.com/gatsby-with-wordpress-caching-downloaded-media-images-to-reduce-build-time/ 

## Coming Up

I plan on writing up a big article about setting up Gatbsy + WordPress + ACF + Polylang for a client ready project with Multilanguage-Support and dynamic content creation through ACF's flexible content fields. I wonder if that would be of interest. Any thoughts and suggestions are highly appreciated.

## References

See the Gatsby documentation of it here: [https://www.gatsbyjs.org/docs/schema-customization/#feeding-remote-images-into-gatsby-image](https://www.gatsbyjs.org/docs/schema-customization/#feeding-remote-images-into-gatsby-image)