Migrando da WordPress Rest API para WP-GraphQL

Comparação entre WordPress Rest API e WP_GraphQL na utilização do WordPress como Headless CMS

Depois da vários anos trabalhando quase que exclusivamente com WordPress, tive contato com o Next JS que me encantou de imediato, apesar de sempre ter achado interessante aplicações criadas com React, sempre tive problemas com elas por causa da renderização client side, o que gera inúmeros problemas para indexação do site pelos mecanismos de busca.

Depois de todos esses anos, o WordPress se tornou um verdadeiro mamute e um CMS bem completo, praticamente um canivete suíço, dá para fazer qualquer coisa com o WordPress, mas isso tem um custo e esse custo são sites muito lentos ou uma necessidade gigantesca de infraestrutura para entregar o site com a melhor performance possível.

Em função da pressão cada vez maior do Google em relação a performance dos sites, principalmente nos celulares, a um aumento de demanda por projetos blockchain, resolvi dar uma chance e tentar estudar React, quando me deparei com o Next JS fiquei encantado, saí de alguém que não sabia nada de React, para alguém que pode entregar um site estático em Next JS em minutos, em um espaço de 2 meses de estudo.

Mas ainda tinha um problema: Precisava que meus clientes pudessem gerenciar o conteúdo, testei inúmeros Headless CMSs do mercado e, a verdade, é que todos são incríveis, para programadores…

Para o cliente médio, que só quer criar conteúdo de maneira fácil, o WordPress ainda é imbatível, então comecei a pesquisar maneiras de usar o WordPress como Headless CMS e o Next JS como frontend. Essa combinação é quase perfeita. De um lado um CMS que quase todo mundo sabe usar de cara e que, se não precisar de muita performance, roda em qualuqer coisa, do outro um framework que gera frontends estáticos com uma performance absurda.

Para essa estrutura funcionar, precisava de uma API para que ambos pudessem conversar.

WordPress (Foto: Markus Winkler / Unsplash)
WordPress (Foto: Markus Winkler / Unsplash)

WP Rest API

Foi a primeira ideia, já que é nativa (todas as instalações recentes de WordPress já vem com ela ativada por padrão), esse site, por exemplo, usa exatamente essa configuração (por enquanto).

Vantagens da API Rest do WordPress

  • Já está instalada e ativada em todas as instalações do WordPress
  • Simples de usar, basta acessar os endpoints e consumir os dados em JSON
  • Farta documentação, com exemplos, dados etc…
  • Muito simples de extender e criar novos endpoints
  • Vários plugins criam seus próprios endpoints aumentando a funcionalidade

Desvantagens da API Rest do WordPress

  • Como quase tudo no WordPress, visa atender a todas as possibilidades e usos imagináveis o que acaba deixando muito complexa
  • O volume de dados gerado pelos endpoints é assustador
  • Esse volume grande dá problemas para fazer o build de sites muito grandes, mesmo usando incremental build

Exemplo dos dados vindos da API Rest do WordPress

{
  "id": 4152,
  "date": "2021-03-21T14:21:15",
  "date_gmt": "2021-03-21T17:21:15",
  "guid": {
    "rendered": "https://brunoalves.space/?p=4152"
  },
  "modified": "2021-06-03T23:55:20",
  "modified_gmt": "2021-06-04T02:55:20",
  "slug": "day-trade-swing-trade-e-holding-ou-position",
  "status": "publish",
  "type": "post",
  "link": "https://brunoalves.space/posts/day-trade-swing-trade-e-holding-ou-position/",
  "title": {
    "rendered": "Day trade, Swing Trade e Holding ou position"
  },
  "content": {
    "rendered": "[...Conteúdo removido para manter a clareza da informação]",
    "protected": false
  },
  "excerpt": {
    "rendered": "<p>Classificações dos investimentos por duração&nbsp; Pessoa começa a querer investir e já dá de cara com esse monte de nomes estranhos, mas não precisa se preocupar, é muito mais simples do que parece. Vou explicar cada um desses termos, para que servem, quais as vantagens e desvantagens de cada um. Primeira explicação é que esses [&hellip;]</p>\n",
    "protected": false
  },
  "author": 8,
  "featured_media": 4153,
  "comment_status": "open",
  "ping_status": "open",
  "sticky": false,
  "template": "",
  "format": "standard",
  "meta": {
    "_et_pb_use_builder": "",
    "_et_pb_old_content": "",
    "_et_gb_content_width": ""
  },
  "categories": [
    1591
  ],
  "tags": [
    1634,
    1635,
    1630,
    1537,
    1637,
    1632,
    1606,
    1636,
    1633,
    1638,
    1631
  ],
  "_links": {
    "self": [
      {
        "href": "https://brunoalves.space/wp-json/wp/v2/posts/4152"
      }
    ],
    "collection": [
      {
        "href": "https://brunoalves.space/wp-json/wp/v2/posts"
      }
    ],
    "about": [
      {
        "href": "https://brunoalves.space/wp-json/wp/v2/types/post"
      }
    ],
    "author": [
      {
        "embeddable": true,
        "href": "https://brunoalves.space/wp-json/wp/v2/users/8"
      }
    ],
    "replies": [
      {
        "embeddable": true,
        "href": "https://brunoalves.space/wp-json/wp/v2/comments?post=4152"
      }
    ],
    "version-history": [
      {
        "count": 0,
        "href": "https://brunoalves.space/wp-json/wp/v2/posts/4152/revisions"
      }
    ],
    "wp:featuredmedia": [
      {
        "embeddable": true,
        "href": "https://brunoalves.space/wp-json/wp/v2/media/4153"
      }
    ],
    "wp:attachment": [
      {
        "href": "https://brunoalves.space/wp-json/wp/v2/media?parent=4152"
      }
    ],
    "wp:term": [
      {
        "taxonomy": "category",
        "embeddable": true,
        "href": "https://brunoalves.space/wp-json/wp/v2/categories?post=4152"
      },
      {
        "taxonomy": "post_tag",
        "embeddable": true,
        "href": "https://brunoalves.space/wp-json/wp/v2/tags?post=4152"
      }
    ],
    "curies": [
      {
        "name": "wp",
        "href": "https://api.w.org/{rel}",
        "templated": true
      }
    ]
  },
  "_embedded": {
    "author": [
      {
        "id": 8,
        "name": "Bruno Alves",
        "url": "",
        "description": "",
        "link": "https://brunoalves.space/author/bruno/",
        "slug": "bruno",
        "avatar_urls": {
          "24": "https://brunoalves.space/wp-content/litespeed/avatar/5/d2eac33ddc48723b38bcb14a4384219c.jpg?ver=1658418862",
          "48": "https://brunoalves.space/wp-content/litespeed/avatar/5/4d0d90993fedc03033368a9104d786a9.jpg?ver=1658418862",
          "96": "https://brunoalves.space/wp-content/litespeed/avatar/5/21cf0dbafeef6943b0b0da8ef262c226.jpg?ver=1658338734"
        },
        "_links": {
          "self": [
            {
              "href": "https://brunoalves.space/wp-json/wp/v2/users/8"
            }
          ],
          "collection": [
            {
              "href": "https://brunoalves.space/wp-json/wp/v2/users"
            }
          ]
        }
      }
    ],
    "wp:featuredmedia": [
      {
        "id": 4153,
        "date": "2021-03-21T14:07:05",
        "slug": "day-trade-swing-trade-e-holding-ou-position-3",
        "type": "attachment",
        "link": "https://brunoalves.space/posts/day-trade-swing-trade-e-holding-ou-position/day-trade-swing-trade-e-holding-ou-position-3/",
        "title": {
          "rendered": "Day trade, Swing Trade e Holding ou position"
        },
        "author": 1,
        "caption": {
          "rendered": "<p>Day trade, Swing Trade e Holding ou position (Pexels / Anna Nekrashevich)</p>\n"
        },
        "alt_text": "Day trade, Swing Trade e Holding ou position",
        "media_type": "image",
        "mime_type": "image/jpeg",
        "media_details": {
          "width": 1280,
          "height": 808,
          "file": "2021/03/Day-trade-Swing-Trade-e-Holding-ou-position.jpg",
          "sizes": {
            "medium": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-300x189.jpg",
              "width": 300,
              "height": 189,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-300x189.jpg"
            },
            "large": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-1024x646.jpg",
              "width": 1024,
              "height": 646,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-1024x646.jpg"
            },
            "thumbnail": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-150x150.jpg",
              "width": 150,
              "height": 150,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-150x150.jpg"
            },
            "medium_large": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-768x485.jpg",
              "width": 768,
              "height": 485,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-768x485.jpg"
            },
            "et-pb-post-main-image": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-400x250.jpg",
              "width": 400,
              "height": 250,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-400x250.jpg"
            },
            "et-pb-post-main-image-fullwidth": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-1080x675.jpg",
              "width": 1080,
              "height": 675,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-1080x675.jpg"
            },
            "et-pb-portfolio-image": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-400x284.jpg",
              "width": 400,
              "height": 284,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-400x284.jpg"
            },
            "et-pb-portfolio-module-image": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-510x382.jpg",
              "width": 510,
              "height": 382,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-510x382.jpg"
            },
            "et-pb-portfolio-image-single": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-1080x682.jpg",
              "width": 1080,
              "height": 682,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-1080x682.jpg"
            },
            "et-pb-gallery-module-image-portrait": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-400x516.jpg",
              "width": 400,
              "height": 516,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-400x516.jpg"
            },
            "et-pb-image--responsive--tablet": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-980x619.jpg",
              "width": 980,
              "height": 619,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-980x619.jpg"
            },
            "et-pb-image--responsive--phone": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position-480x303.jpg",
              "width": 480,
              "height": 303,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position-480x303.jpg"
            },
            "full": {
              "file": "Day-trade-Swing-Trade-e-Holding-ou-position.jpg",
              "width": 1280,
              "height": 808,
              "mime_type": "image/jpeg",
              "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position.jpg"
            }
          },
          "image_meta": {
            "aperture": "0",
            "credit": "",
            "camera": "",
            "caption": "",
            "created_timestamp": "0",
            "copyright": "",
            "focal_length": "0",
            "iso": "0",
            "shutter_speed": "0",
            "title": "",
            "orientation": "0",
            "keywords": []
          }
        },
        "source_url": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position.jpg",
        "_links": {
          "self": [
            {
              "href": "https://brunoalves.space/wp-json/wp/v2/media/4153"
            }
          ],
          "collection": [
            {
              "href": "https://brunoalves.space/wp-json/wp/v2/media"
            }
          ],
          "about": [
            {
              "href": "https://brunoalves.space/wp-json/wp/v2/types/attachment"
            }
          ],
          "author": [
            {
              "embeddable": true,
              "href": "https://brunoalves.space/wp-json/wp/v2/users/1"
            }
          ],
          "replies": [
            {
              "embeddable": true,
              "href": "https://brunoalves.space/wp-json/wp/v2/comments?post=4153"
            }
          ]
        }
      }
    ],
    "wp:term": [
      [
        {
          "id": 1591,
          "link": "https://brunoalves.space/investimentos/",
          "name": "Investimentos",
          "slug": "investimentos",
          "taxonomy": "category",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/categories/1591"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/categories"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/category"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?categories=1591"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        }
      ],
      [
        {
          "id": 1634,
          "link": "https://brunoalves.space/posts/tag/buy-and-hold/",
          "name": "Buy and Hold",
          "slug": "buy-and-hold",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1634"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1634"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1635,
          "link": "https://brunoalves.space/posts/tag/curto-prazo/",
          "name": "Curto Prazo",
          "slug": "curto-prazo",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1635"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1635"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1630,
          "link": "https://brunoalves.space/posts/tag/day-trade/",
          "name": "Day Trade",
          "slug": "day-trade",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1630"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1630"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1537,
          "link": "https://brunoalves.space/posts/tag/estrategias/",
          "name": "estratégias",
          "slug": "estrategias",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1537"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1537"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1637,
          "link": "https://brunoalves.space/posts/tag/estrategias-de-investimento/",
          "name": "Estratégias de investimento",
          "slug": "estrategias-de-investimento",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1637"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1637"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1632,
          "link": "https://brunoalves.space/posts/tag/holding/",
          "name": "Holding",
          "slug": "holding",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1632"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1632"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1606,
          "link": "https://brunoalves.space/posts/tag/longo-prazo/",
          "name": "longo prazo",
          "slug": "longo-prazo",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1606"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1606"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1636,
          "link": "https://brunoalves.space/posts/tag/medio-prazo/",
          "name": "Médio Prazo",
          "slug": "medio-prazo",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1636"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1636"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1633,
          "link": "https://brunoalves.space/posts/tag/position/",
          "name": "Position",
          "slug": "position",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1633"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1633"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        },
        {
          "id": 1638,
          "link": "https://brunoalves.space/posts/tag/prazo-de-investimento/",
          "name": "Prazo de investimento",
          "slug": "prazo-de-investimento",
          "taxonomy": "post_tag",
          "_links": {
            "self": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags/1638"
              }
            ],
            "collection": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/tags"
              }
            ],
            "about": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/taxonomies/post_tag"
              }
            ],
            "wp:post_type": [
              {
                "href": "https://brunoalves.space/wp-json/wp/v2/posts?tags=1638"
              }
            ],
            "curies": [
              {
                "name": "wp",
                "href": "https://api.w.org/{rel}",
                "templated": true
              }
            ]
          }
        }
      ]
    ]
  }
}

Como acessar esses dados usando a API Rest do WordPress?

só acessar o endpoint: /wp-json/wp/v2/posts/id_do_post?_embed

Wp GraphQL

Um plugin acrescenta as funcionalidades do GraphQL ao WordPress, criando um endpoint que executa consultas nesta linguagem de consulta especializada em APIs. Quando comecei o projeto de migração do Pinkfire ficou bem claro que usar a API Rest do WordPress não daria certo, nos primeiros testes as páginas ficavam gigantescas (algumas com mais de 1MB) só de dados que vinham da API. Ou seja, o build time estava dando mais de 45 minutos e muitas vezes acabava quebrando.

Foi então que resolvi começar os testes com o GraphQL e os resultados se mostram muito promissores, nos primeiros testes já consegui baixar os dados vindos da API para menos de 128kb, o que permitiu completar o build com certa facilidade.

Vantages do WP-GraphQL

  • Pode montar a consulta só com os dados que vai usar. Se é um projeto que não precisa do autor, basta não trazer os dados do autor e todos os demais metadados que o autor
  • A velocidade aumenta consideravelmente
  • Consultas mais complexas e não previstas pela API Rest do WordPress são possíveis sem a necessidade de criar novos endpoints
  • Já existem vários plugins que dão funcionalidades extras ao WP-GraphQL (interação com plugins de SEO, Woocommerce, custom fields etc…)

Desvantagens do WP-GraphQL

  • Precisa instalar um plugin para ativar (nem todas as instalações do WordPress permitem isso)
  • Precisa aprender GraphQL, não que ela seja complicada, mas é um mundo bem diferente do SQL, por exemplo.
  • Não tem paginação tradicional, só por cursor, a não ser que instale um plugin para isso (paginação por cursor é ótimo para endless scroll e realt time, mas causa sérios problemas quando sua ideia é pré-gerar todas as páginas). Aqui tem um ótimo artigo comparando os dois tipos de paginação.
  • A WP Rest APi é mais leniente quanto as dados (Como o WordPress aceita quase tudo que o usuário quiser fazer existe uma grande chance de seus dados sejam bastante inconsistentes)

Exemplo dos dados vindos da API WP-GraphQL

{
  "data": {
    "postBy": {
      "id": "cG9zdDo0MTUy",
      "author": {
        "node": {
          "name": "Bruno Alves"
        }
      },
      "categories": {
        "nodes": [
          {
            "name": "Investimentos",
            "slug": "investimentos"
          }
        ]
      },
      "commentCount": null,
      "comments": {
        "nodes": []
      },
      "content": ""[...Conteúdo removido para manter a clareza da informação]"",
      "dateGmt": "2021-03-21T17:21:15",
      "excerpt": "<p>Classificações dos investimentos por duração&nbsp; Pessoa começa a querer investir e já dá de cara com esse monte de nomes estranhos, mas não precisa se preocupar, é muito mais simples do que parece. Vou explicar cada um desses termos, para que servem, quais as vantagens e desvantagens de cada um. Primeira explicação é que esses [&hellip;]</p>\n",
      "featuredImage": {
        "node": {
          "altText": "Day trade, Swing Trade e Holding ou position",
          "mediaItemUrl": "https://bacloud-savein.cdn.jelastic.net/wp-content/uploads/sites/5/2021/03/Day-trade-Swing-Trade-e-Holding-ou-position.jpg"
        }
      },
      "modifiedGmt": "2021-06-04T02:55:20",
      "slug": "day-trade-swing-trade-e-holding-ou-position",
      "title": "Day trade, Swing Trade e Holding ou position"
    }
  },
  "extensions": {
    "debug": [
      {
        "type": "DEBUG_LOGS_INACTIVE",
        "message": "GraphQL Debug logging is not active. To see debug logs, GRAPHQL_DEBUG must be enabled."
      }
    ]
  }
}

Como dá para ver, só vem o que eu preciso para renderizar o post.

Como acessar esses dados usando a API Rest do WordPress?

Acessando o endpoint do WP-GraphQL e enviando a consulta abaixo (o Apollo Client faz um trabalho excepcional de deixar esse trabalho bem simplificado).

query getPostByID {
  postBy(postId: 4152) {
    id
    author {
      node {
        name
      }
    }
    categories {
      nodes {
        name
        slug
      }
    }
    commentCount
    comments {
      nodes {
        author {
          node {
            avatar {
              url
            }
            name
          }
        }
        content(format: RENDERED)
        dateGmt
      }
    }
    content(format: RENDERED)
    dateGmt
    excerpt(format: RENDERED)
    featuredImage {
      node {
        altText
        mediaItemUrl
      }
    }
    id
    modifiedGmt
    slug
    title
  }
}

Qual é melhor WP Rest API ou WP-GraphQL?

Considerando tudo exposto acima, para mim, fica bem claro que o uso do WP-GraphQL facilita muito as coisas, além de diminuir muito a quantidade de dados que precisam trafegar, seja na hora do build, seja na hora de incrementar novas páginas criadas.

Já estou com uma biblioteca pronta para fazer essa ponte entre o WP-GraphQL e o Next JS, só preciso de tempo para colocar essa biblioteca publicamente no meu GitHub (segue lá para receber um aviso quando eu postar) e pretendo migrar todos os projetos que usam essa arquitetura, hoje e daqui para frente.

Porém, apesar de odiar a resposta depende, sempre tem um depende. Em casos que só precise de uma solução rápida, não tenha um volume muito grande de dados (muitos posts ou posts muito grandes) ou que não possa instalar os plugins necessários, vou continuar com a API Rest, só por causa da velocidade e simplicidade de implementação (é bom quando está tudo pronto).