website-astro/src/content/fragments/fr/nuxt-graphql-static.md

141 lines
3.6 KiB
Markdown
Raw Normal View History

2022-12-28 10:36:15 +01:00
---
title: Site statique et requêtes GraphQL avec Nuxt.js
subtitle: Le client graphql est roi.
lang: fr
slug: "nuxt-graphql-static"
createdAt: "2022-06-08T14:24:06.000Z"
updatedAt: "2022-09-08T13:43:33.000Z"
excerpt: Quand le module gql le plus utilisé ne fonctionne pas…
tags: ["nuxt.js"]
2023-05-09 12:26:03 +02:00
type: fragments
2022-12-28 10:36:15 +01:00
---
## Le problème
Je me suis heurté à un villain bug en utilisant Nuxt en mode génération statique complète et le client [nuxt apollo](https://github.com/nuxt-community/apollo-module "Dépôt github du module nuxt apollo (nouvel onglet)").
Après quelques recherches, voici [le bug constaté par quelqu'un d'autre](https://github.com/nuxt-community/apollo-module/issues/339 "Bug visible sur le dépôt github du module nuxt/apollo (nouvel onglet)") sur github.
Il semblerait que le module en l'état ne gère pas correctement la génération statique avec `nuxt generate`.
Je trouvais toujours des appels à mon API locale après la génération statique et la navigation depuis les `<nuxt-link>` ne fonctionnait pas.
## La solution 🙌
Heureusement, il existe un autre module Nuxt pour gérer les requêtes GraphQL&nbsp;!
[Nuxt graphql request à la rescousse&nbsp;!](https://github.com/gomah/nuxt-graphql-request "Dépôt github du module (nouvel onglet)")
### La conf
```javascript
// nuxt.config.js
buildModules: [
'nuxt-graphql-request',
],
graphql: {
clients: {
default: {
endpoint: 'http://API_URL/graphql',
options: {
headers: {
authorization: 'Bearer API_TOKEN',
},
},
},
},
},
```
### La requête
La meilleure méthode à ce jour est d'utiliser `asyncData` dans les pages et `fetch` dans les composants. Utiliser `fetch` dans les pages ne fonctionne pas bien du tout avec `nuxt generate`.
J'installe également le paquet `graphql-tag` (uniquement en `devDependencies`) afin de pouvoir importer directement des fichiers `.gql`
Exemple de fichier&nbsp;:
```graphql
# homepage.gql
query {
homepage {
title
subtitle
hero {
id
alt
}
}
}
```
#### Dans une page
```javascript
// index.vue
<script>
import homepageQuery from '~/graphql/queries/singles/homepage'
export default {
async asyncData({ $graphql }) {
const data = await $graphql.default.request(homepageQuery)
return { data }
},
}
</script>
```
#### Dans un composant
Il est plus prudent d'attendre que `fetch` ait reçu une réponse avant d'afficher quoi que ce soit. On peut utiliser `$fetchState` afin d'être tranquille ([documentation](https://fr.nuxtjs.org/docs/2.x/components-glossary/pages-fetch "Documentation sur la méthode fetch (nouvel onglet)")).
```javascript
// Header.vue
<template>
<header v-if="!$fetchState.pending">
</header>
</template>
<script>
import headerQuery from '~/graphql/queries/singles/header'
export default {
data() {
return {
data: {},
}
},
async fetch() {
try {
const data = await this.$graphql.default.request(headerQuery)
this.data = data
} catch (error) {
console.error(JSON.stringify(error, undefined, 2))
}
},
}
</script>
```
### Les options
Pour passer des options à la requête, par exemple pour une version multilingue avec [nuxt/i18n](https://i18n.nuxtjs.org/ "Documentation de nuxt i18n (nouvel onglet)") et/ou un paramètre d'url dans le cadre d'une page dynamique&nbsp;:
```javascript
// _slug.vue
<script>
import articleQuery from '~/graphql/queries/articles'
export default {
async asyncData({ $graphql, app, params }) {
const locale = app.i18n.localeProperties.iso
const data = await $graphql.default.request(articleQuery, {
code: locale,
slug: params.slug,
})
return { data }
},
}
</script>
```