Contents
Introducción
En este tutorial vas a aprender, con todo lujo de detalles, a consumir GraphQL expuesto por WPGraphQL desde JavaScript en el frontend de WordPress. Cubriremos desde los conceptos básicos hasta ejemplos prácticos: cómo montar consultas, enviar variables, autenticar peticiones (nonce y JWT), integrar con librerías como Apollo Client o graphql-request, manejar paginación, errores, caching y recomendaciones de seguridad y rendimiento para producción.
Requisitos y preámbulos
- Un sitio WordPress con el plugin WPGraphQL instalado y activado.
- Acceso para añadir código PHP en tu tema o plugin (p. ej. functions.php o un plugin propio) para encolar y pasar datos al script frontend.
- Conocimientos básicos de JavaScript y GraphQL (queries, variables, fragments).
1. ¿Cuál es el endpoint GraphQL de WPGraphQL?
Por defecto WPGraphQL expone el endpoint en:
- /graphql (ruta relativa a la URL de tu sitio, p. ej. https://midominio.com/graphql)
El endpoint acepta peticiones POST con el body en JSON: { query: …, variables: {…} } y responde JSON con la forma estándar GraphQL: { data: …, errors: […] }.
2. Configuración básica en WordPress: encolar tu script y pasar datos
Es una práctica común pasar al script frontend la URL del endpoint y el nonce de WordPress para peticiones autenticadas. Usa wp_enqueue_script y wp_localize_script (o wp_add_inline_script) para inyectar variables.
esc_url_raw( home_url( /graphql ) ),
nonce => wp_create_nonce( wp_rest ) // se puede usar para autenticación con nonce
)
)
}
add_action( wp_enqueue_scripts, mi_tema_enqueue_scripts )
?>
3. Ejemplo mínimo: consumir GraphQL con fetch (cliente ligero)
Este ejemplo muestra una consulta simple que pide títulos y slugs de posts. Se utiliza fetch nativo y se manejan errores básicos. Ideal para proyectos muy simples o sitios sin librerías de GraphQL.
// app.js
const GRAPHQL_URL = window.WPGRAPHQL_SETTINGS.graphqlUrl
const query =
query GetPosts(first: Int = 10) {
posts(first: first) {
nodes {
id
title
slug
date
}
}
}
async function fetchGraphQL(query, variables = {}) {
const res = await fetch(GRAPHQL_URL, {
method: POST,
headers: {
Content-Type: application/json
// X-WP-Nonce: window.WPGRAPHQL_SETTINGS.nonce // si necesitas autenticar como usuario logueado
},
body: JSON.stringify({ query, variables })
})
const json = await res.json()
if (!res.ok json.errors) {
const message = json.errors ? JSON.stringify(json.errors) : res.statusText
throw new Error(GraphQL error: message)
}
return json.data
}
// Uso
fetchGraphQL(query, { first: 5 })
.then(data => {
console.log(Posts:, data.posts.nodes)
})
.catch(err => {
console.error(err)
})
4. Enviar encabezados de autenticación
Hay varios escenarios de autenticación dependiendo de si necesitas realizar consultas públicas o privadas:
- Consultas públicas: No requieren autenticación.
- Usuarios autenticados en frontend: Puedes usar el nonce de WP REST (X-WP-Nonce) para validar la sesión del usuario WPGraphQL puede respetarlo si lo configuras.
- JWT / Token-based: Para APIs headless o apps externas es habitual usar un plugin JWT (p. ej. JWT Auth) y enviar Authorization: Bearer lttokengt.
Ejemplo enviando nonce:
const res = await fetch(GRAPHQL_URL, {
method: POST,
headers: {
Content-Type: application/json,
X-WP-Nonce: window.WPGRAPHQL_SETTINGS.nonce
},
body: JSON.stringify({ query, variables })
})
5. Uso de librerías: graphql-request (muy simple) y Apollo Client (completo)
graphql-request (ligero)
Instalación:
- npm install graphql-request
Ejemplo:
import { GraphQLClient, gql } from graphql-request
const client = new GraphQLClient(window.WPGRAPHQL_SETTINGS.graphqlUrl, {
headers: {
Content-Type: application/json
// X-WP-Nonce: window.WPGRAPHQL_SETTINGS.nonce
}
})
const query = gql
query GetPost(id: ID!) {
post(id: id, idType: DATABASE_ID) {
title
content
date
}
}
const data = await client.request(query, { id: 42 })
console.log(data)
Apollo Client (cuando necesitas cache, SSR y ecosistema)
Apollo ofrece política de cache avanzada, manejo de errores, enlace de autenticación y más. Ejemplo de inicialización para frontend SPA:
import { ApolloClient, InMemoryCache, HttpLink } from @apollo/client
const httpLink = new HttpLink({
uri: window.WPGRAPHQL_SETTINGS.graphqlUrl,
credentials: same-origin, // para que incluya cookies cuando aplique
headers: {
// X-WP-Nonce: window.WPGRAPHQL_SETTINGS.nonce
}
})
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
posts: {
// policy para paginación por cursor si lo deseas
keyArgs: false,
merge(existing = {}, incoming = {}) {
return {
...incoming,
nodes: [...(existing.nodes []), ...(incoming.nodes [])]
}
}
}
}
}
}
})
})
// Uso: client.query({ query: gql..., variables: {...} })
6. Variables, fragments y consultas complejas
Siempre que uses variables evita interpolar directamente valores dentro de la string de la consulta esto mejora seguridad y reutilización. También usa fragments para evitar repetir campos.
import { gql } from @apollo/client
const postFields = gql
fragment PostFields on Post {
id
title
excerpt
slug
date
}
const GET_POSTS = gql
query GetPosts(first: Int = 10, after: String) {
posts(first: first, after: after) {
pageInfo {
hasNextPage
endCursor
}
nodes {
...PostFields
}
}
}
{postFields}
7. Paginación: cursor-based (recomendada) y page-based
WPGraphQL suele proveer paginación por cursor (relay style) con campos pageInfo/edges/nodes. Implementa lógica para solicitar más nodos usando endCursor y hasNextPage.
// ejemplo de cargar más con fetch
let after = null
async function loadMore() {
const data = await fetchGraphQL(
query(first: Int, after: String) {
posts(first: first, after: after) {
pageInfo { hasNextPage endCursor }
nodes { id title slug }
}
}
, { first: 10, after })
// append nodes a UI...
if (data.posts.pageInfo.hasNextPage) {
after = data.posts.pageInfo.endCursor
} else {
after = null
}
}
8. Manejo de errores y retries
GraphQL puede devolver errores en la propiedad errors además de un status HTTP 200. Siempre revisa y muestra mensajes apropiados. Para resiliencia añade reintentos exponenciales o usa librerías como retry o políticas integradas en Apollo.
async function fetchGraphQLWithRetries(query, variables = {}, retries = 3) {
let attempt = 0
while (attempt < retries) {
try {
const res = await fetch(GRAPHQL_URL, { ... })
const json = await res.json()
if (json.errors) throw new Error(JSON.stringify(json.errors))
return json.data
} catch (err) {
attempt
if (attempt >= retries) throw err
await new Promise(r => setTimeout(r, 200 attempt)) // backoff
}
}
}
Si tu frontend no está servido desde el mismo dominio de WordPress (p. ej. app independiente), debes configurar cabeceras CORS en el servidor. Para peticiones autenticadas con cookies asegúrate de usar credentials: include o same-origin y configurar el servidor para permitirlas.
10. SSR y SSG (Next.js, Nuxt o similar)
Para renderizado en servidor, realiza las peticiones GraphQL desde el servidor (getServerSideProps / getStaticProps en Next.js) usando la URL completa del endpoint y, si usas tokens, pásalos desde variables de entorno o cookies del request. No expongas secretos en JavaScript del cliente.
// Ejemplo Next.js: getServerSideProps
export async function getServerSideProps(context) {
const res = await fetch(process.env.WP_GRAPHQL_URL /graphql, {
method: POST,
headers: { Content-Type: application/json },
body: JSON.stringify({
query: query { posts(first:5){ nodes{ id title slug } } }
})
})
const json = await res.json()
return { props: { posts: json.data.posts.nodes } }
}
11. Persisted queries y reducción de payload
Para reducir tamaño y mejorar seguridad, puedes usar consultas persistentes: guardas consultas en el servidor y en el cliente envías sólo un identificador. Hay plugins y soluciones para WPGraphQL que facilitan esto (p. ej. wp-graphql-persisted-queries). Otra alternativa es comprimir y minimizar consultas o usar HTTP/2.
12. Optimización y performance
- Solicita sólo los campos necesarios (evita overfetching).
- Implementa cache en el cliente (Apollo InMemoryCache) y en el servidor (transient caching, Varnish, CDN).
- Usa paginación para listas grandes y lazy loading en UI.
- Considera usar fragment caché y cachés HTTP para respuestas públicas.
- Evita N 1 queries en resolvers personalizados: si implementas resolvers en WPGraphQL atiende el rendimiento de consultas relacionadas.
13. Seguridad: validación y limitación
- Limita la profundidad y complejidad de las consultas si te exponen a abusos (depth limiting).
- Rate limiting a nivel de servidor o CDN para evitar DDoS.
- Valida y sanitiza cualquier dato que pase desde el cliente al servidor, especialmente si implementas mutaciones que alteren contenido.
- Usa tokens y scopes para endpoints sensibles, y evita exponer credenciales en el bundle público.
14. Mutations: crear, actualizar y borrar desde JS
WPGraphQL soporta mutations para crear y modificar contenido (si el esquema y permisos lo permiten). Para mutaciones autenticadas utiliza nonce o token y el usuario debe tener permisos adecuados.
const mutation =
mutation CreatePost(input: CreatePostInput!) {
createPost(input: input) {
post {
id
title
slug
}
clientMutationId
}
}
const variables = {
input: {
clientMutationId: abc123,
title: Mi nuevo post desde frontend,
content: Contenido...,
status: PUBLISH
}
}
const res = await fetch(GRAPHQL_URL, {
method: POST,
headers: {
Content-Type: application/json,
X-WP-Nonce: window.WPGRAPHQL_SETTINGS.nonce
},
body: JSON.stringify({ query: mutation, variables })
})
const json = await res.json()
if (json.errors) throw new Error(JSON.stringify(json.errors))
console.log(Post creado:, json.data.createPost.post)
15. Plugins y extensiones útiles
- WPGraphQL – plugin base.
- Plugins JWT para autenticación – distintos mantenedores.
- Persisted queries – para consultas guardadas.
- Apollo Client – cliente GraphQL completo.
16. Checklist final antes de pasar a producción
- Verificar permisos y roles para mutations y queries privadas.
- Habilitar límites de complejidad y profundidad si el endpoint es público.
- Configurar CORS correctamente si el frontend está en otro dominio.
- Configurar caching (CDN, cache de GraphQL o transients).
- Monitorizar errores y métricas (tiempos de respuesta, tasa de errores).
- Minimizar la exposición de secretos en cliente usar almacenamiento seguro en servidor para tokens.
Ejemplos adicionales y casos de uso
Ejemplo: Usar graphql-request con JWT
import { GraphQLClient, gql } from graphql-request
const token = localStorage.getItem(jwt_token) // token obtenido tras login
const client = new GraphQLClient(window.WPGRAPHQL_SETTINGS.graphqlUrl, {
headers: {
Authorization: Bearer {token}
}
})
const query = gqlquery { viewer { id name } }
const data = await client.request(query)
console.log(Usuario:, data.viewer)
Ejemplo: registrar un script y pasar datos seguros desde servidor
rest_url(/graphql), // alternativa para entornos con prefijos
nonce => wp_create_nonce(wp_rest)
))
}
add_action(wp_enqueue_scripts, mi_plugin_enqueue)
?>
Conclusión
Consumir WPGraphQL desde JavaScript en el frontend es directo si conoces las piezas clave: endpoint /graphql, cómo pasar headers (nonce o tokens), y la manera de estructurar las consultas y mutaciones. Elige la herramienta adecuada para tu caso: fetch o graphql-request si buscas simplicidad Apollo si necesitas caching sofisticado, gestión de estado y SSR avanzado. Prioriza seguridad (noexponer secretos), rendimiento (cache y paginación) y manejo de errores para entregar una experiencia robusta al usuario.
|
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |
