📌

Nuxt x Composition API x Hasura x TypeScriptを実装する

2021/07/27に公開

まずはHasura Cloudでプロジェクトを作っておきましょう
https://hasura.io/docs/latest/graphql/cloud/projects/create.html

接続に必要なGraphQLのAPIエンドポイントと、アクセス時にヘッダーに必要なAdmin Secretを控えておきます

次にNuxtプロジェクトをnpxで作ります

$ npx create-nuxt-app nuxt-composable-hasura

次に必要なライブラリ群をインストールしていきましょう(各ライブラリの導入に必要なnuxt.config.jsへの設定はここでは省きます)

まずNuxtでcomposition APIを使うためのライブラリを入れます

https://composition-api.nuxtjs.org/

次に「Nuxt内で」且つ、「Composable APIで」、apolloを使うためのライブラリを2つ入れます

https://github.com/nuxt-community/apollo-module
https://v4.apollo.vuejs.org/guide-composable/setup.html

そして、@nuxtjs/apolloで設定したApollo Clientを、プラグインという形でApollo Composableから呼び出せるよう登録します

nuxt.config.js
// nuxt.config.jsのapolloで、先程取得したHasura情報をセットして
apollo: {
  clientConfigs: {
    default: {
      httpEndpoint: process.env.GRAPHQL_ENDPOINT,
      httpLinkOptions: {
        headers: {
          'X-Hasura-Admin-Secret': process.env.HASURA_SECRET,
        },
      },
    },
  },
}
src/plugins/apollo.ts
// 今作ったApollo ClientをDefaultApolloClientとして登録する

import { Plugin } from '@nuxt/types'
import { provide, onGlobalSetup } from '@nuxtjs/composition-api'
import { DefaultApolloClient } from '@vue/apollo-composable'

const ApolloPlugin: Plugin = ({ app }) => {
  onGlobalSetup(() => {
    provide(DefaultApolloClient, app.apolloProvider.defaultClient)
  })
}

export default ApolloPlugin
nuxt.config.js
// pluginの登録を忘れずに
plugins: ['@/plugins/apollo'],

お次は、graphqlをTypeScriptから使うために、graphql-codegenのライブラリを入れていきます

https://www.graphql-code-generator.com/

自分の場合、環境変数を使いたいのでcodegen.jsでdotenvを呼び出す形で設定しています

codegen.js
require('dotenv').config()

module.exports = {
  overwrite: true,
  schema: [
    {
      [process.env.GRAPHQL_ENDPOINT]: {
        headers: {
          'x-hasura-admin-secret': process.env.HASURA_SECRET,
        },
      },
    },
  ],
  documents: ['./src/**/*.{graphql,gql}'],
  generates: {
    './src/generated/graphql.ts': {
      plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
    },
    './graphql.schema.json': {
      plugins: ['introspection'],
    },
  },
}

このファイルがプロジェクトルート直下にある状態でと、スキーマファイルと、TypeScript向けのファイルが発行されます

あとは実際に使うスクリプトを設定して

src/graphql/queries/getUsers.gql
query getUsers {
  users(order_by: { id: asc }) {
    id
    name
  }
}

yarn gql-genを実行します。

するとsrc/generated/graphql.tsというファイルで、TypeScriptの型付きのファイルが発行されます(getUsersというクエリは、GetUsersDocumentというDocumentNode型に変換されます)

これを@vue/apollo-composableから呼び出します

src/pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script lang="ts">
import { defineComponent } from '@vue/composition-api'
import { GetUsersDocument } from '@/generated/graphql'
import { useQuery, useResult } from '@vue/apollo-composable'

export default defineComponent({
  name: 'IndexPage',
  setup() {
    const { result } = useQuery(GetUsersDocument)
    const users = useResult(result, [], (data) => data?.users)

    return { users }
  },
})
</script>

mutationも同様に実装できます(細かい@vue/apollo-composableの使い方は、公式のドキュメントに任せます)

今回のコードはこんな感じ

https://github.com/DialBird/nuxt-composable-hasura

Discussion