Usando Gatsby JS con wordpress

May 23, 2020 • ☕️ 6 minutos de lectura

Usando Gatsby JS con wordpress

Hoy aprenderemos como extraer datos de Wordpress usando Gatsby, de esta manera tendremos un gestor de contenidos en pocos minutos y podremos crear un frontend con usando Gatsby Js, un framework libre basado en React.

¿Que necesitamos?

Wordpress

Para empezar, necesitamos instalar Wordpress, si queremos ahorrar costes, podemos usar la plataforma gratuita, aunque tendremos la limitación de no poder instalar ningún plugin, por eso os recomiendo instalarlo en algún hosting.

Si queremos insertar campos adiccionales, como podría ser una imagen, debemos instalar Advanced Custom Fields, este plugin es gratuito pero viene limitado.

Existe una versión de pago de este plugin Advanced Custom Fields Pro que vale alrededor de 20€ y es mucho más completo, permitiendo galerías entre otras cosas.

Otro plugin que usaremos en nuestro ejemplo, será ACF to REST API. Este plugin convertirá nuestro wordpress en una API Rest que podremos consumir.

Ahora instalaremos Gatsby, bueno el CLI de Gatsby.

Gatsby JS

npm install -g gatsby-cli

Con el CLI de Gatsby, podremos crear nuestro nuevo proyecto, este comando nos generará todo lo necesario para poder empezar

gatsby new gatsby-con-wordpress

Usaremos gatsby-source-wordpress para extraer lo datos a nuestro Gatsby desde nuestro wordpress con API REST de WordPress.

npm i gatsby-source-wordpress

Para configurarlo, debemos editar el fichero gatsby-config.js.

module.exports = {
  siteMetadata: {
    title: `Gatsby Default Starter`,
    description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
    author: `@gatsbyjs`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `gatsby-transformer-sharp`,    `gatsby-plugin-sharp`,    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `gatsby-starter-default`,
        short_name: `starter`,
        start_url: `/`,
        background_color: `#663399`,
        theme_color: `#663399`,
        display: `minimal-ui`,
        icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
      },
    },
    {      resolve: "gatsby-source-wordpress",      options: {        // baseUrl: es la dirección de nuestro wordpress, sin http:// o sin https://        baseUrl: "blog.dominio.com",        // protocol: espero que sea https        //Si no usas https, te recomiendo encarecidamente que lo pongas. https://letsencrypt.org/es/        protocol: "https",        // hostingWPCOM: es para indicar si está alojada en wordpress.com, nosotros lo marcaremos en false.        hostingWPCOM: false,        // useACF: Si activamos useACF en true, indicamos que vamos a usar ACF plugin de wordpress. https://wordpress.org/plugins/advanced-custom-fields/        useACF: true,        // searchAndReplaceContentUrls: Busca y reemplaza las url del contenido Wordpress.        searchAndReplaceContentUrls: {          sourceUrl: "https://blog.tudominio.com",          replacementUrl: "http://localhost",        },        // Set how many simultaneous requests are sent at once.        concurrentRequests: 10,        // use a custom normalizer which is applied after the built-in ones.        normalizer: function({ entities }) {          return entities        },      },    },    // `gatsby-plugin-offline`,
  ],
}

Todo esto nos ha servido para pasar de wordpress a el GraphQL de nuestro proyecto con Gatsby.

Podemos verlo en: http://localhost:8000/___graphql y haciendo la siguiente consulta para que nos devuelva todas las páginas de nuestro wordpress.

query MyQuery {
  allWordpressPage {
    edges {
      node {
        link
        id
        slug
        title
        content
      }
    }
  }
}

Creación de págnia para listar post y pages de wordpress

Crear páginas en Gatsbyjs es muy sencillo, basta con crear un fichero js dentro de /src/pages/nombre.js y crearemos una página que se llama http://localhost/nombre.

Para ver los resultados crearemos el fichero blog.js dentro de nuestro directoriod e páginas y haremos una consulta a Graphql para coger los datos que necesitemos.

import React, { Component } from "react"
import { Link, graphql } from "gatsby"
import Img from "gatsby-image"
import Layout from "../components/layout"
import SEO from "../components/seo"

class Posts extends Component {
  render() {
    function FeaturedImage(image) {
      if (!image) {
        return null
      }
      console.log(image)
      return (
        <div>
          <Img
            fluid={image.localFile.childImageSharp.fluid}
            alt=""
            className="img-thumb"
          />
        </div>
      )
    }

    const data = this.props.data
    return (
      <>
        <Layout>
          <SEO title="Posts" />
          <div>
            <h1>Pages</h1>
            {data.allWordpressPage.edges.map(({ node }) => (
              <div key={node.slug}>
                <Link to={node.slug}>
                  <h2>{node.title}</h2>
                  {FeaturedImage(node.featured_media)}
                </Link>
                <div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
              </div>
            ))}
          </div>

          <h1>Posts</h1>
          <div>
            {data.allWordpressPost.edges.map(({ node }) => (
              <div key={node.slug}>
                <Link to={`/blog/${node.slug}`}>
                  <div>
                    <h2>{node.title}</h2>
                  </div>
                  {FeaturedImage(node.featured_media)}
                </Link>
                <div dangerouslySetInnerHTML={{ __html: node.excerpt }} />
              </div>
            ))}
          </div>
        </Layout>
      </>
    )
  }
}

export default Posts

export const pageQuery = graphql`
  query {
    allWordpressPage {
      edges {
        node {
          id
          title
          excerpt
          slug
        }
      }
    }
    allWordpressPost {
      edges {
        node {
          title
          excerpt
          slug
          featured_media {
            source_url
            localFile {
              childImageSharp {
                sizes(maxWidth: 1800) {
                  ...GatsbyImageSharpSizes
                }
                fluid(maxWidth: 400) {
                  ...GatsbyImageSharpFluid
                }
                resize(width: 400, jpegProgressive: true) {
                  src
                }
              }
            }
          }
        }
      }
    }
  }
`

Creación de páginas para los detalles de posts y pages de wordpress

Editamos nuestro fichero gatsby-node.js

const path = require(`path`)
const slash = require(`slash`)
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions

  // hacemos una consulta para obtener todos los posts y páginas de wordpress
  const result = await graphql(`
    query {
      allWordpressPage {
        edges {
          node {
            id
            title
            excerpt
            slug
          }
        }
      }
      allWordpressPost {
        edges {
          node {
            id
            title
            excerpt
            slug
          }
        }
      }
    }
  `)

  // componente de plantilla para detalles de páginas
  const pageTemplate = path.resolve(`./src/templates/page.js`)
  // nodo de página. Solo usaremos el Slug de WordPress para el slug.
  // Queremos crear una página detallada para cada
  const pages = result.data.allWordpressPage.edges
  pages.forEach((edge, index) => {
    const previous = index === pages.length - 1 ? null : pages[index + 1].node
    const next = index === 0 ? null : pages[index - 1].node
    // Los complementos y sitios pueden usar funciones como "createPage"
    // para interactuar con Gatsby.
    // Gatsby usa Redux para administrar su estado interno.
    createPage({
      // Se requiere que cada página tenga una 'path' también
      // como un componente de plantilla. El `contexto` es
      // opcional pero a menudo es necesario para que la plantilla
      // puede consultar datos específicos de cada página.
      path: `/${edge.node.slug}/`,
      component: slash(pageTemplate),
      context: {
        id: edge.node.id,
        previous,
        next,
      },
    })
  })

  // Ahora ahoremos lo mismo pero para los post aunque con una
  // diferencia de que la url empezará por /blog/slug-del-post

  const postTemplate = path.resolve(`./src/templates/post.js`)
  const posts = result.data.allWordpressPost.edges

  result.data.allWordpressPost.edges.forEach((edge, index) => {
    const previous = index === posts.length - 1 ? null : posts[index + 1].node
    const next = index === 0 ? null : posts[index - 1].node
    createPage({
      path: `/blog/${edge.node.slug}/`,
      component: slash(postTemplate),
      context: {
        id: edge.node.id,
        previous,
        next,
      },
    })
  })
}

Ahora por último nos queda crear los componentes que mostrarn los detalles de nuestros posts y pages. Recuerda que gatsby-node.js

const pageTemplate = path.resolve(`./src/templates/page.js`)
// ...

Creamos el componente Page /templates/page.js

import React, { Component } from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

class Page extends Component {
  render() {
    const StaticPage = this.props.data.wordpressPage

    return (
      <>
        <Layout>
          <SEO title={StaticPage.title} />
          <h1>{StaticPage.title}</h1>
          <div dangerouslySetInnerHTML={{ __html: StaticPage.content }} />
        </Layout>
      </>
    )
  }
}

export default Page

export const pageQuery = graphql`
  query($id: String!) {
    wordpressPage(id: { eq: $id }) {
      title
      content
    }
  }
`

Creamos el componente Post /templates/post.js

import React, { Component } from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"

class Post extends Component {
  render() {
    const StaticPost = this.props.data.wordpressPost

    return (
      <>
        <Layout>
          <SEO title={StaticPost.title} />
          <h1>{StaticPost.title}</h1>
          <div dangerouslySetInnerHTML={{ __html: StaticPost.content }} />
        </Layout>
      </>
    )
  }
}

export default Post

export const postQuery = graphql`
  query($id: String!) {
    wordpressPost(id: { eq: $id }) {
      title
      content
    }
  }
`

Si quieres descargar el código, puedes haerlo aquí gatsby-wordpress-starter