Tell us about your project

Gatsby logo

With the rising popularity of Gatsby as a go-to framework for building website frontend, there are more and more demands for solutions in regard to optimization (both SEO and performance vise).

One of the problems when it comes to SEO optimization of your website would be the loading of external images on your pages. The core of the problem comes from the fact that whatever platform you are using as your backend, whether it is Drupal or Contentful or something else, the images will be stored there. And the easiest way to display such images would be to just point the ‘src’ attribute of your img tags to the appropriate location of the image and be done with it.

The problem with this solution is that the search engines will continue to store the images with the URL of your backend instead of your page which could lead to lower SEO scores.

The way to prevent this is to download and store the images in build time when the pages are being created and load them from Gatsby’s storage so as to be able to display them with a proper path.

This can be done relatively easily by implementing the createRemoteFileNode method from Gatsby’s ‘gatsby-source-plugin’ during execution of createPages in gatsby-node.js like so (don’t forget to import the ‘createRemoteFileNode’ method from ‘gatsby-source-plugin’):

const fileNode = await createRemoteFileNode({
  url: `${API_URL}${image.url}`,
  parentNodeId: edge.node[locale].id.toString(),
  getCache,
  createNode,
  createNodeId,
});

The url parameter in this case would need to be the path to the asset that needs to be downloaded and the parentNodeId would be the ID of the page or node the asset is supposed to be attached to.

For this method to work properly you would need to add ‘action’, ‘getCache’ and ‘createNodeId’ parameters to your createPage method in gastby-node.js like so:

exports.createPages = async ({ graphql, actions, getCache, createNodeId }) => {

And also initialize the ‘createNode’ method like so:

const { createNode } = actions

With this setup, every time the createRemoteFileNode is called it will download the asset located on the url provided to the method and store it in the static folder of your Gatsby site.

After that you can get the path of a specific asset by using graphQL query and providing the id of the newly created file node like so:

const publicUrl = await graphql(`
  query LogoQuery {
   allFile(filter: {id: {eq: "${fileNode.id}"}}) {
    edges {
     node {
      publicURL
     }
    }
   }
  }
`)

Now all that is left is adding the ‘publicURL’ to your pages parameters. Assuming you are using createPage method for generating your pages this can be done by adding the variable as part of the page’s context. After that, all that is left is getting the parameter from the page’s context and imputing the ‘publicURL’ variable into the image display method you are using.


Grigor Varga