Manejo de imágenes con Gatsby

En la entradas anteriores (1 y 2) se mostró cómo vincular un proyecto de Gatsby con un sitio de WordPress utilizado como Headless CMS, en esta ocasión, se profundizará en la presentación que se puede dar al proyecto haciendo uso de imágenes. Antes de comenzar, es importante profundizar en un componente llamado gatsby-image, que está diseñado para trabajar con las consultas de GraphQL de Gatsby y que hace uso de técnicas de cargado y optimización avanzadas para desplegar el contenido de una manera más rápida, optimizada y responsiva.

Entendiendo gatsby-image

Como se mencionó en la introducción, gatsby-image será el componente encargado de procesar y mostrar las imágenes en el sitio de Gatsby desarrollado, para esto, es importante destacar que este componente no es un reemplazo directo de la etiqueta <img>, pero es probable que si se desea realizar alguna implementación de esta etiqueta, no funcione como es esperado; por lo que se recomienda hacer uso de gatsby-image y entender los escenarios para su uso.

Para realizar el procesamiento de imágenes, un plugin entra en juego, gatsby-plugin-sharp, plugin basado en la biblioteca de procesamiento de imágenes Sharp, esta biblioteca pone a disposición métodos de bajo nivel de procesamiento de imágenes y que generalmente no son expuestos al desarrollador, sino que Gatsby los utiliza internamente.

Tomando en cuenta lo anterior, se procederá a mostrar el primer ejemplo. Se debe entender que al crear un proyecto de Gatsby, este ya cuenta con la biblioteca gatsby-image por defecto, sin embargo, se debe asegurar la presencia de los paquetes gatsby-transformer-sharp y gatsby-plugin-sharp, en caso de no contar con estas bibliotecas, se pueden instalar con npm.

npm install gatsby-transformer-sharp gatsby-plugin-sharp

Una vez instaladas, hay que asegurar que estas se encuentren en el gatsby-config.js del proyecto, como atributos del objeto plugins.

plugins: [
  ...,
  
  `gatsby-transformer-sharp`,
  `gatsby-plugin-sharp`,
  
  ...
]

Además de esto, es necesario contar con una manera de acceder a los documentos del proyecto, para esto se utiliza un complemento llamado gatsby-source-filesystem, que se encarga de poner archivos a disposición de las consultas de GraphQL, esto con el fin de hacer accesibles las imágenes del proyecto. Es importante asegurar que el archivo gatsby-config.js incluya esta configuración para indicar a Gatsby cuál es la ruta desde la cual se obtendrán las imágenes, además de los complementos incluidos anteriormente.

plugins: [
  ...
  
  {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,
    `gatsby-plugin-sharp`,
  
  ...
]

En el siguiente bloque de código se puede ver a gatsby-image en acción, y se trata del componente exportado en src/components/image.js. Este componente es generado de manera automática cuando se crea un proyecto de Gatsby.

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Image = () =&gt; {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fluid(maxWidth: 300) {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  return <Img />
}

export default Image

Como se puede ver en el código, el componente exportado realiza una consulta de GraphQL para acceder a la imagen gatsby-astronaut.png, que debe existir bajo la ruta src/images/. La consulta muestra otras características interesantes de la manera de consultar imágenes, como el hecho de que se puede nombrar a la imagen, el uso de consultas dinámicas, y que la imagen se puede obtener de diferentes formas y tamaños, en este caso se utiliza el atributo fluid, que forma parte de los atributos explicados en la siguiente sección.

Tipos de imágenes

Teniendo en cuenta los conceptos mencionados anteriormente, es claro que las imágenes se obtienen mediante métodos de GraphQL, lo importante ahora es entender dónde entra la optimización, para esto existen dos tipos de imágenes: fijas (fixed) y fluidas(fluid). Estos tipos de imagen proporcionan imágenes responsivas de diferentes tamaños (1x, 1.5x, etc.).

Fixed

Al consultar una imagen como fija, automáticamente se generan imágenes para diferentes resoluciones basadas en un conjunto de un ancho y un alto proporcionados mediante código, Gatsby genera las imágenes para las densidades de pixel 1x, 1.5x y 2x utilizando el elemento . Una vez consumida la información de la imagen, esta puede utilizarse en un elemento Img.

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Image = () =&gt; {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fixed {
            ...GatsbyImageSharpFixed
          }
        }
      }
    }
  `)

  return <Img />
}

export default Image

El ejemplo anterior muestra la manera en que se utilizaría una imagen fija, es importante identificar que las imágenes fijas tienen las siguientes opciones que pueden ser especificadas:

  • width: (int, default: 400)
  • height: (int)
  • quality: (int, default: 50)

El resultado de la consulta devuelve los siguientes valores:

  • base64 (string)
  • aspectRatio (float)
  • width (float)
  • height (float)
  • src (string)
  • srcSet (string)

Una manera práctica de acceder a esta información es haciendo uso de los fragments de GatsbyImageSharpFixed, como se muestra a continuación

childImageSharp {
	fixed(width: 500, height: 500) {
		...GatsbyImageSharpFixed
	}
}

Estos fragments varían de acuerdo al tipo de imagen utilizada, en el caso de las imágenes fijas, se pueden utilizar los siguientes:

  • GatsbyImageSharpFixed
  • GatsbyImageSharpFixed_noBase64
  • GatsbyImageSharpFixed_tracedSVG
  • GatsbyImageSharpFixed_withWebp
  • GatsbyImageSharpFixed_withWebp_noBase64
  • GatsbyImageSharpFixed_withWebp_tracedSVG

Cada uno de los sufijos presentes en los fragments provoca que la imagen cargue de manera distinta o que la información devuelta varíe de acuerdo a la selección realizada.

noBase64

Por defecto, las imágenes son precargadas utilizando un efecto blur para dar la impresión de que el sitio carga de manera más rápida y ordenada, al seleccionar esta opción, se indica que no se desea utilizar este efecto.

tracedSVG

Reemplaza el efecto blur para utilizar un trazado en svg de lo que será el contenido de la imagen.

withWebp

Permite trabajar automáticamente con imágenes en el formato WebP si este es soportado por el navegador, en caso contrario se vuelve a la imagen previa.

Más información sobre los fragments puede consultarse en: https://www.gatsbyjs.com/plugins/gatsby-image/#fragments.

Fluid

Este tipo de imágenes se utilizan cuando no se conoce el tamaño exacto o la proporción que tendrá la imagen en la página, y genera imágenes responsivas de acuerdo a diferentes tamaños de pantalla. Las imágenes de tipo fluido se van a contraer o expandir de acuerdo al contenedor que las albergue. La manera de integrar imágenes fluidas es muy similar a las fijas:

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Image = () =&gt; {
  const data = useStaticQuery(graphql`
    query {
      placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
        childImageSharp {
          fluid {
            ...GatsbyImageSharpFluid
          }
        }
      }
    }
  `)

  return <Img />
}

export default Image

De igual forma, las imágenes fluidas reciben algunos parámetros:

  • maxWidth (int, default: 800)
  • maxHeight(int)
  • quality (int, default: 50)
  • srcSetBreakpoints (array of int, default: [])
  • background (string, default: rgba(0,0,0,1))

El resultado de la consulta devuelve los siguientes valores:

  • base64 (string)
  • aspectRatio (float)
  • src (string)
  • srcSet (string)
  • srcSetType (string)
  • sizes (string)
  • originalImg (string)

El esquema de fragments también se maneja de manera similar al de las imágenes fijas, pero en este caso las opciones son:

  • GatsbyImageSharpFluid
  • GatsbyImageSharpFluid_noBase64
  • GatsbyImageSharpFluid_tracedSVG
  • GatsbyImageSharpFluid_withWebp
  • GatsbyImageSharpFluid_withWebp_noBase64
  • GatsbyImageSharpFluid_withWebp_tracedSVG

Existen otras opciones disponibles para la transformación de imágenes, pero estas están fuera del alcance de esta entrada, si se desea consultar más a profundidad, revisar la documentación de Gatsby.