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 🙂 |