140 lines
3.3 KiB
Markdown
Executable file
140 lines
3.3 KiB
Markdown
Executable file
---
|
|
title: Static website and GraphQL queries with Nuxt.js
|
|
subtitle: Graphql client is king.
|
|
lang: en
|
|
permalink: "nuxt-graphql-static"
|
|
createdAt: "2022-06-08T14:24:06.000Z"
|
|
updatedAt: "2022-09-08T13:43:33.000Z"
|
|
excerpt: When the most used gql module doesn't work…
|
|
tags: ["nuxt.js"]
|
|
type: snippets
|
|
---
|
|
|
|
## The problem
|
|
|
|
I encountered a nasty bug while using static generation with Nuxt and [nuxt apollo](https://github.com/nuxt-community/apollo-module "Dépôt github du module nuxt apollo (new tab)") client.
|
|
I found [the issue](https://github.com/nuxt-community/apollo-module/issues/339 "Github issue on nuxt/apollo repository (new tab)") already reported on github.
|
|
|
|
It seems the module doesn't handle static generation correctly with `nuxt generate`.
|
|
|
|
I could find request to my local API url after the static generation. Moreover, it also seemed like `<nuxt-link>` navigation was broken.
|
|
|
|
## The solution 🙌
|
|
|
|
Fortunately, there is another Nuxt module that handles GraphQL requests!
|
|
|
|
[Nuxt graphql request to the rescue!](https://github.com/gomah/nuxt-graphql-request)
|
|
|
|
### The conf
|
|
|
|
```javascript
|
|
// nuxt.config.js
|
|
buildModules: [
|
|
'nuxt-graphql-request',
|
|
],
|
|
graphql: {
|
|
clients: {
|
|
default: {
|
|
endpoint: 'http://API_URL/graphql',
|
|
options: {
|
|
headers: {
|
|
authorization: 'Bearer API_TOKEN',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
```
|
|
|
|
### The request
|
|
|
|
The best approach so far is to use `asyncData` in pages and `fetch` in components. Using `fetch` in pages does not work well at all with `nuxt generate`.
|
|
|
|
I also install the `graphql-tag` package (only in `devDependencies`) to be able to import directly `.gql` files.
|
|
|
|
Query example:
|
|
|
|
```graphql
|
|
# homepage.gql
|
|
query {
|
|
homepage {
|
|
title
|
|
subtitle
|
|
hero {
|
|
id
|
|
alt
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Inside a 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>
|
|
```
|
|
|
|
#### Inside a component
|
|
|
|
It is safer to wait until `fetch` has received a response before displaying anything. You can use `$fetchState` to be sure ([documentation](https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch "Documentation on the fetch hook (new tab)")).
|
|
|
|
```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>
|
|
```
|
|
|
|
### Options
|
|
|
|
To pass options to the request, for example for a multilingual version with [nuxt/i18n](https://i18n.nuxtjs.org/) and/or a url parameter in a dynamic page:
|
|
|
|
```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,
|
|
permalink: params.slug,
|
|
})
|
|
return { data }
|
|
},
|
|
}
|
|
</script>
|
|
```
|