Gatsby.JS: Working with Images in Markdown Posts and Pages

[Fuente:

https://www.gatsbyjs.com/docs/working-with-images-in-markdown/

https://www.gatsbyjs.com/docs/using-gatsby-image/

]

Using Gatsby Image to Prevent Image Bloat

Using images in Gatsby components and pages requires four steps to take advantage of performance benefits.

Using images in Gatsby requires a few different plugins.

Install gatsby-transformer-sharp and gatsby-plugin-sharp to transform and process your imagesgatsby-image is a package that includes a component you’ll use later in “View”.

npm install gatsby-transformer-sharp gatsby-plugin-sharp gatsby-image gatsby-source-filesystem

gatsby-image is a React component designed to work seamlessly with Gatsby’s GraphQL queries (gatsby-image plugin README). It combines Gatsby’s native image processing capabilities with advanced image loading techniques to easily and completely optimize image loading for your sitesgatsby-image uses gatsby-plugin-sharp to power its image transformations.

Warning: gatsby-image is not a drop-in replacement for <img />. It’s optimized for fixed width/height images and images that stretch the full width of a container. Some ways you can use <img /> won’t work with gatsby-image.

Here’s a demo site that uses the gatsby-image plugin

gatsby-image includes the tricks you’d expect from a modern image component. It:

  • uses the new IntersectionObserver API to cheaply lazy load images
  • holds an image’s position so your page doesn’t jump around as images load
  • makes it easy to add a placeholder—either a gray background or a blurry version of the image.

For more complete API information, check out the Gatsby Image API docs.

Problem

Large, unoptimized images dramatically slow down your site.

But creating optimized images for websites has long been a thorny problem. Ideally, you would:

  • Resize large images to the size needed by your design
  • Generate multiple smaller images so smartphones and tablets don’t download desktop-sized images
  • Strip all unnecessary metadata and optimize JPEG and PNG compression
  • Efficiently lazy load images to speed initial page load and save bandwidth
  • Use the “blur-up” technique or a “traced placeholder” SVG to show a preview of the image while it loads
  • Hold the image position so your page doesn’t jump while the images load

Doing this consistently across a site feels like a task that can never be completed. You manually optimize your images and then… several images are swapped in at the last minute or a design-tweak shaves 100px of width off your images.

Most solutions involve a lot of manual labor and bookkeeping to ensure every image is optimized.

This isn’t ideal. Optimized images should be easy and the default.

Solution

With Gatsby, you can make the experience of working with images way, way better.

gatsby-image is designed to work seamlessly with Gatsby’s native image processing capabilities powered by GraphQL and Sharp. To produce perfect images with minimal effort, you can:

  1. Install gatsby-image and other, necessary dependencies like gatsby-plugin-sharp and gatsby-transformer-sharp:npm install gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp
  2. Add the newly installed plugins and transformer plugins to your gatsby-config.js
  3. module.exports = {
      plugins: [`gatsby-plugin-sharp`, `gatsby-transformer-sharp`],
    }

     

  4. Configure gatsby-source-filesystem to load images from a folder. In order to use GraphQL to query the image files, the files need to be in a location that is known to Gatsby. This requires an update to gatsby-config.js to configure the plugin. Feel free to replace the path option to reference wherever your images are located in your project.
  5. module.exports = {
      plugins: [
        `gatsby-transformer-sharp`,
        `gatsby-plugin-sharp`,
        {
          resolve: `gatsby-source-filesystem`,
          options: {
            path: `${__dirname}/src/data/`,
          },
        },
      ],
    }

     

When building Gatsby sites composed primarily of Markdown pages or posts, insertion of images can enhance the content. You can add images in multiple ways.

In sites like a blog, you may want to include a featured image that appears at the top of a page. One way to do this is to grab the image filename from a frontmatter field and then transform it with gatsby-plugin-sharp in a GraphQL query.

This solution assumes you already have programmatically generated pages from Markdown with renderers like gatsby-transformer-remark or gatsby-plugin-mdx. If not, take a read through up to Part 7 of the Gatsby Tutorial. This will build upon the tutorial and as such, gatsby-transformer-remark will be used for this example.

Note: This can be done similarly using MDX as well. Instead of the markdownRemark nodes in GraphQL, Mdx can be swapped in and should work.

To start out, download the plugins for Gatsby-image as mentioned in Using gatsby-image.

 

Configuring for images and posts in the same directory

If your images are in the same directory as the Markdown files, sourcing and resolving the images can be done in one configuration. For example, if your Markdown pages and images are located together in a /pages directory, both content types will be automatically picked up by GraphQL as part of Gatsby’s data layer.

gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
    `gatsby-transformer-remark`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/pages`,
      },
    },
  ],
}

Then, in an example Markdown file, add a field called featuredImage:

src/pages/my-favorite-doggos.md
---
title: My Favorite Doggos
featuredImage: pupperino.png
---

Content goes here!

The next step will be to incorporate the data into a template with a GraphQL query, which can be found later in this guide.

Configuring for images and posts in different directories

There are also occasions when you may want to source images from a different directory than where your Markdown posts or pages are located, such as in an external /images folder. You can set this up by specifying two distinct sources, one for the pages and the other for images:

Querying for images from Frontmatter

Now that you’ve sourced Markdown and image data, you can query for featured images in GraphQL. If a filepath points to an actual image, it will be transformed into a File node in GraphQL and then you can get the image data out of it by using the childImageSharp field.

This can be added to the GraphQL query in a Markdown template file. In this example, a Fluid query is used to make a responsive image.

src/templates/blog-post.js

export const query = graphql`
  query PostQuery($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 800) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    }
  }
`

Also in the Markdown post template, import the gatsby-image package and pass the results of the GraphQL query into an <Img /> component.

src/templates/blog-post.js

import React from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import Img from "gatsby-image"

export default function BlogPost({ data }) {
  let post = data.markdownRemark

  let featuredImgFluid = post.frontmatter.featuredImage.childImageSharp.fluid

  return (
    <Layout>
      <div>
        <h1>{post.frontmatter.title}</h1>
        <Img fluid={featuredImgFluid} />
        <div dangerouslySetInnerHTML={{ __html: post.html }} />
      </div>
    </Layout>
  )
}

export const query = graphql`
  query PostQuery($slug: String!) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      frontmatter {
        title
        featuredImage {
          childImageSharp {
            fluid(maxWidth: 800) {
              ...GatsbyImageSharpFluid
            }
          }
        }
      }
    }
  }
`

Your featured image should now appear on the generated page right below the main header. Tada!

Inline images with gatsby-remark-images

You may also include images in the Markdown body itself. The plugin gatsby-remark-images comes in handy for this.

Start out by installing gatsby-remark-images and gatsby-plugin-sharp.

npm install gatsby-remark-images gatsby-plugin-sharp

Also make sure that gatsby-source-filesystem is installed and points at the directory where your images are located.

Configure the plugins in your gatsby-config file. As with the previous example, either Remark or MDX can be used.

Using the Transformer Remark Plugin

Here is a similar example using the gatsby-transformer-remark plugin instead of gatsby-plugin-mdx. Put the gatsby-remark-images plugin within the plugins option field of gatsby-transformer-remark.

gatsby-config.js

module.exports = {
  plugins: [
    `gatsby-plugin-sharp`,
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 800,
            },
          },
        ],
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        path: `${__dirname}/src/posts`,
      },
    },
  ],
}

With the configurations above, you can use the default Markdown syntax for images. They will be processed by Sharp and appear as if you placed them in a gatsby-image component.

![Hopper The Rabbit](./rabbit-friend.png)