🙌
TypeScript & GraphQL でToDoアプリを開発する #4
⬅️前回の記事はこちら
⭐️Apollo Clientの起動
frontend/にplugins/apollo-client.tsを作成
apollo-client.ts
import { defineNuxtPlugin } from '#app'
import { ApolloClient, InMemoryCache, HttpLink } from '@apollo/client/core'
export default defineNuxtPlugin((nuxtApp) => { // Nuxtにプラグイン(Apollo)を注入
const httpLink = new HttpLink({
uri: 'http://localhost:4001/graphql', // GraphQLサーバーのエンドポイントを指定
})
const apolloClient = new ApolloClient({
link: httpLink, // 通信方法(httpLink)を指定
cache: new InMemoryCache(), // クエリ結果などのキャッシュの設定
})
nuxtApp.provide('apollo', apolloClient) // Nuxtにapolloという名前でApollo Clientを登録
})
frontend/にgraphql/queries.tsを作成
queries.ts
import { gql } from '@apollo/client/core'
export const GET_TODOS = gql`
query GetTodos {
getTodos { # getTodosリゾルバ(クエリ)を呼び出し、Todoの一覧を取得
id
title
completed
}
}
`
frontend/graphql/にmutations.tsを作成
mutations.ts
import { gql } from '@apollo/client/core'
export const CREATE_TODO = gql`
mutation CreateTodo($title: String!) {
createTodo(title: $title) { # createTodoリゾルバ(ミューテーション)を呼び出し、Todoを作成
id
title
completed
}
}
`
export const UPDATE_TODO = gql`
mutation UpdateTodo($id: Int!, $title: String, $completed: Boolean) {
updateTodo(id: $id, title: $title, completed: $completed) { # updateTodoリゾルバ(ミューテーション)を呼び出し、Todoを更新
id
title
completed
}
}
`
export const DELETE_TODO = gql`
mutation DeleteTodo($id: Int!) {
deleteTodo(id: $id) # deleteTodoリゾルバ(ミューテーション)を呼び出し、Todoを削除
}
`
frontend/にpages/index.vueを作成
(Apollo Clientが正しく動作しているか確認するため、最小限の内容で作成)
index.vue
<template>
<h1>🚀 index.vueの表示に成功!</h1>
</template>
frontend/のapp.vueを削除
※Nuxtが用意した「ようこそページ」
pages/ディレクトリを未作成時に表示される用のものなので削除でOK
frontend/にcomposables/useTodos.tsを作成
useTodos.ts
import { useAsyncData, useNuxtApp } from '#app'
import { GET_TODOS } from '@/graphql/queries'
// Todo型を定義
type Todo = {
id: number
title: string
completed: boolean
}
// Todo一覧を取得するためのカスタムコンポーザブル(useTodos)を定義
export const useTodos = () => {
const { $apollo } = useNuxtApp() // NuxtアプリケーションからApollo Clientを取得
// useAsyncDataを使って非同期でデータ取得(キャッシュキーは'todos')
const { data, pending, error, refresh } = useAsyncData('todos', async () => {
// Apollo Clientを使ってGraphQLクエリを送信
const result = await $apollo.query<{ getTodos: Todo[] }>({
query: GET_TODOS, // 実行するGraphQLクエリ
fetchPolicy: 'no-cache', // キャッシュを使わず、常に最新のデータを取得
});
// 取得したTodo一覧をID順にソートして返す
return result.data.getTodos.slice().sort((a, b) => a.id - b.id)
})
// 呼び出し元のコンポーネントが使えるように必要な値を返す
return {
todos: data, // Todo一覧のデータ
pending, // データ取得中かどうか(ローディング状態)
error, // エラーが発生した場合の情報
refresh // データを再取得するための関数
}
}
frontend/にtypes/apollo.d.tsを作成
apollo.d.ts
import { ApolloClient } from '@apollo/client/core'
// NuxtAppに$apolloを追加するための型定義(明示的なインターフェース定義)
export interface NuxtApp {
$apollo: ApolloClient<any>
}
// Nuxt 3 のアプリケーションに対して $apollo を型として追加する(型拡張)
declare module '#app' {
interface NuxtApp {
$apollo: ApolloClient<any>
}
}
// Vueコンポーネント に対して this.$apollo を型として追加する(型拡張)
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$apollo: ApolloClient<any>
}
}
frontend/package.jsonのscriptsブロックにポートを追記
package.json
//修正前
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
package.json
//修正後
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev --port 3001", //←ポートを追記
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
frontend/で npm run dev を実行
% npm run dev
http://localhost:3001 にアクセスしてindex.vueの内容が表示されたら成功
🚀Apollo Clientの起動が完了!!!
#4のおわりに
Apollo Client の起動 お疲れさまでした。
次回は本格的に画面を開発して動作確認をします。
〜Vueの紹介〜
VueはUI構築のための JS/TSフレームワークです。
ここでは、Vueの特徴を3つに絞って紹介します。
◼️公式エコシステムが充実している
- 状態管理やビルドツールなど、必要な機能が公式で揃っており、構成に迷いにくくなっています。
◼️単一ファイルコンポーネント(SFC)で構造が明確
- .vue という単一ファイルに、テンプレート・ロジック・スタイル をまとめて記述できます。
.vue
<template>...</template>
<script>...</script>
<style scoped>...</style>
◼️学習コストが低い
- HTML/CSS/JavaScriptの基礎知識があれば、直感的に書き始めることができます。
Discussion