Essential Gatsby plugins. Part 1, SEO and Images

Gatsby plugins let you do complex or repetitive work with little or no effort. In this post we’ll see some common requirements your app can have and what plugins you can use in order to satisfy them. So the plugins are grouped by the following requirements.

The guide became toο long for a single post so broke it in 3 parts. It’s for people who are familiar with React applications but are new to Gatsby. I assume that you already set up your development environment for Gatsby. Also note that when you configure a new plugin, in order to work, you’ll have to restart your development server with Ctrl + C on the console and by typing gatsby develop.

Let’s start our journey through the gatsby-plugins with the first category which is the Search Engine Optimization or SEO of our application.

*Page content at a glance:

1) SEO

The plugins in this section help you manage and improve the SEO of your application. They are all easy install and configure and they don’t take much time to add to any new Gatsby application you create (as all plugins in this guide, to be honest).

gatsby-plugin-react-helmet

The first one doesn’t need a lot of introduction, it’s the integration of the popular library react-helmet into Gatsby. React helmet lets you manipulate the contents of the document’s head. For example, if you want to change the title of the page:

<html>
  <head>
    <title>The Lakers won't make the playoffs in 2018/19 season.</title>  </head>
  <body>
    <!-- content -->
  </body>
</html>

you can do the following with react-helmet, in any React component:

// MyComponent.jsx
import Helmet from "react-helmet";

const MyComponent = () => (
  <div>
    <Helmet>      <title>The Lakers won't make the playoffs in 2018/19 season.</title>    </Helmet>  </div>
);

gatsby-plugin-react-helmet is listed under the SEO section because you can add anything in the head of the document including meta tags which are regularly used for SEO. Of course with react-helmet you can additionally load external scripts and CSS inside the <head></head> element. For example, you can download jQuery if you want (just kidding).

The installation and the configuration of react-helmet is the simplest you can get for a Gatsby plugin. You install it with:

npm i gatsby-plugin-react-helmet react-helmet

and then you configure it by adding a string in your gatsby-config.js:

// gatsby-config.js
module.exports = {
  plugins: [`gatsby-plugin-react-helmet`]};

An approach for SEO with react helmet that works for me is to create a SEO component and include it in my pages and post templates. You can see an example below.

// src/components/SEO.jsx
import React from "react";
import Helmet from "react-helmet";

const SEO = ({ title, description, image, url, keywords, lang }) => (
  <Helmet>
    <html lang={lang} />
    <title>{title}</title>
    <meta name="description" content={description} />
    <meta name="keywords" content={keywords} />
    <meta property="og:url" content={url} />
    <meta property="og:title" content={title} />
    <meta property="og:description" content={description} />
    <meta property="og:image" content={image} />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content={title} />
    <meta name="twitter:description" content={description} />
    <meta name="twitter:image" content={image} />
  </Helmet>
);

The next plugin we’ll see is the gatsby-plugin-feed.

gatsby-plugin-feed

gatsby-plugin-feed creates an RSS feed from the content of your app (markdown posts) and places it at the root of your public folder (public/rss.xml). For example, the rss.xml for this blog was, at some point, the following:

<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/"
 xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"
 version="2.0">
  <channel>
    <title><![CDATA[Dev Diary]]></title>
    <description><![CDATA[Welcome to Dev Diary. This is a blog about programming. My name is Mark, i'm a JavaScript developer and i want to share my experiences with programming. ]]></description>
    <link>https://markoskon.com</link>
    <generator>RSS for Node</generator>
    <lastBuildDate>Thu, 25 Oct 2018 16:32:42 GMT</lastBuildDate>
    <item>
      <title><![CDATA[An overview of essential Gatsby plugins]]></title>
      <description><![CDATA[Gatsby plugins enable you to do  complex / repetitive  or straight up  boring  work with  little or no effort . In this post we’ll see some…]]></description>
... (hundreds of lines of xml)

You can also see the current one if you wish. Anyway, you get the idea. I don’t believe is something many people will use but why not have it. You install it with:

npm i gatsby-plugin-feed

and the minimal configuration is the following:

// gatsby-config.js
module.exports = {
  siteMetadata: {
    title: "Gatsby Default Starter",
    siteUrl: "http://localhost:8000",
    description: "Checking out gatsby plugins"
  },
  plugins: [`gatsby-plugin-feed`]
};

Ok, I actually lied here. This is the minimal configuration if you already have set up the markdown plugins, you created some markdown posts and you also created some pages from those posts… If you don’t, you’ll get errors. So be patient with this one and use it after you read the markdown section of the guide.

One thing to remember is that the RSS feed is not generated when you run the development server with gatsby develop but when you build the site. So in order to see it in action, you’ll have to build first with gatsby build and then serve it locally with gatsby serve. If we assume that your site is available at http://localhost:5000 you’ll visit http://localhost:5000/rss.xml and you should be able to see the result. Of course, like many other plugins you can configure it further. The next plugin we’ll see generates automatically something similar.

gatsby-plugin-sitemap

The sitemap plugin, as the name suggests, creates automatically a sitemap.xml file and places it at the root of your public folder. The sitemap contains any route a user can visit in your site. An example of a generated sitemap is the following:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
  xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:mobile="http://www.google.com/schemas/sitemap-mobile/1.0"
  xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
<url> <loc>https://markoskon.com/basic-gatsby-plugins/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/firebase-react-virtualized/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/publish-npm-modules/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/wordpress-development/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/about/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/contact/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>https://markoskon.com/</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
</urlset>

You can also take a look at the current one. Search engines love sitemaps so it’s a good idea to have one generated automatically for you. This way you won’t have to worry if your sitemap is still valid when you add/change/delete your content. You can install it with:

npm i gatsby-plugin-sitemap

and configure it with the default options as shown below:

// gatsby-config.js
module.exports = {
  siteMetadata: {
    siteUrl: "http://localhost:8000"
  },
  plugins: [`gatsby-plugin-sitemap`]
};

Note that you have to specify a siteUrl, and in order to see it you’ll have to build your site with gatsby build. Like the feed plugin, you can override the default configuration if you wish so and specify some advanced options. We continue with plugins that generate automatically stuff for us with gatsby-plugin-robots-txt.

gatsby-plugin-robots-txt

Well as you may have guessed it, the Robots txt plugin creates automatically for you a robots.txt file. This file is used by search engine crawlers, and you can specify inside it instructions for them. On those instructions, you specify how you wish your site to be crawled. Of course, they may not follow those instructions, it’s up to them. As the previous plugins you install it with:

npm i gatsby-plugin-robots-txt

and configure it:

// gatsby-config.js
module.exports = {
  siteMetadata: {
    siteUrl: "http://localhost:8000"
  },
  plugins: [`gatsby-plugin-robots-txt`]
};

The site URL is needed by the plugin so don’t forget to include that. The generated robots.txt is the following:

User-agent: *
Allow: /
Sitemap: http://localhost:8000/sitemap.xml
Host: localhost:8000

Again you’ll have to build your site to see it, and of course, you can further customize it. This was the last of the SEO plugins. Now let’s talk about images.

2) Images

In this section, we’ll explain how you can display images effectively in your app. Some of the things we’ll see are:

  • how you can lazy load images
  • how you can progressive load them with blur or tracedSVG techniques
  • how to create responsive image sizes for different screen sizes.

The first plugin that is used as a base for image manipulation is gatsby-source-filesystem.

gatsby-source-filesystem

The source filesystem plugin parses the files you specify in gatsby-config.js and creates File nodes that you can use in your pages with Gatsby’s graphql API. You can install it with:

npm i gatsby-source-filesystem

and you configure it in gatsby-config.js to load your images as shown below:

// gatsby-config.js
// We assume that your images are located at src/images folder.
const path = require(`path`);

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: "images",
        path: path.join(__dirname, `src`, `images`)
      }
    }
  ]
};

Because the File nodes are not usually what you want, this plugin is used as a base for other “transformer” plugins. In our case, it’s used by an image manipulation plugin the gatsby-transformer-sharp.

gatsby-transformer-sharp

The transformer sharp plugin uses the Sharp image manipulation library and creates ImageSharp nodes that we can use in our pages with graphql queries. Those nodes contain fields like fluid, fixed, original and resize. In later examples, we’ll use the fluid property. This plugin goes along with the gatsby-plugin-sharp

gatsby-plugin-sharp

Gatsby plugin sharp is a “lower level” plugin that actually processes the images. You install both of them with:

npm i gatsby-plugin-sharp gatsby-transformer-sharp

and your gatsby-config.js file changes to:

// gatsby-config.js
// We assume that your images are located at src/images folder.
const path = require(`path`);

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: "images",
        path: path.join(__dirname, `src`, `images`)
      }
    },
    `gatsby-plugin-sharp`,    `gatsby-transformer-sharp`  ]
};

At this point if we place an image called my-image.jpg in src/images/ folder, we can write a query to request it at our src/pages/index.js page. We’ll we use the src of the fluid property:

// src/pages/index.js
import React from "react";
import { graphql } from "gatsby";

const IndexPage = ({ data }) => (
  <div>
    <h1>Here is an image!</h1>
    <img src={data.myImage.childImageSharp.fluid.src} alt="Cool stuff" />
  </div>
);

export const query = graphql`
  query {
    myImage: file(relativePath: { regex: "/my-image/" }) {
      childImageSharp {
        fluid(maxWidth: 1920) {
          src
        }
      }
    }
  }
`;
export default IndexPage;

We see that we can use this childImageSharp object (from a File node) by getting the image src and use it in a plain HTML <img/> element. But the better way is to use the last plugin which is the gatsby-image.

gatsby-image

This plugin, unlike the other image plugins we saw earlier, is actually a React component and as a result, doesn’t require any further configuration in the gatsby-config.js file. The Img component offers lazy loading by default and progressive loading with blur or tracedSVG techniques. Additionally creates a source element:

<source srcset="our images in various sizes" />

and downloads the correct images depending on the screen size. Finally, it can resize large images to smaller sizes, optimize them and create a placeholder div with the corresponding size so the page won’t “jump” when they are finished downloading. We can install it with:

npm i gatsby-image

and import it at our page component. So our index page would become:

// src/pages/index.js
import React from "react";
import { graphql } from "gatsby";
import Img from "gatsby-image";
const IndexPage = ({ data }) => (
  <div>
    <h1>Here is an image!</h1>
    <Img fluid={data.myImage.childImageSharp.fluid} />  </div>
);

export const query = graphql`
  query {
    myImage: file(relativePath: { regex: "/my-image/" }) {
      childImageSharp {
        fluid(maxWidth: 1920) {
          ...GatsbyImageSharpFluid        }
      }
    }
  }
`;
export default IndexPage;

If you wish you can add some empty space before the image:

<div style={{height: "200vh"}}>
  Some empty space follows... Scroll down to see the image
</div>

and open your developer tools to see that it’s actually lazy-loaded. I encourage you to try the image plugins mentioned in this section, you’d be amazed by how easily you can accomplish this functionality! There is also a nice gatsby-image example that uses these 4 plugins in detail. You can see many ways that you can use the image plugins, not only one or two I showed here.

If you are not bored to death at this point (you are not right? right..?), we can continue our journey to Gatsby’s “transformer” plugins. In the second part of the tutorial, we’ll see how you can use them to parse and transform markdown (.md) files to something your app can use.