0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[vue3/typeScript ]Vue Apollo で GraphQLを試したサンプル解説

Last updated at Posted at 2022-09-20

この記事の概要

Vue3でTypeScriptを使いGraphQLを試してみた

  • Vue3対応
  • Vue Apollo v3(vue3に正式対応しているのはv4から 開発中)
  • GraphQLを実行するまでのサンプル解説

GraphQLについて

APIのためのクエリー言語であり、既存のデータを使ってクエリーを実行するためのランタイム。

クライアントからサーバーのデータを取得する場合REST APIが主な手段だった
REST APIとの比較については以下記事をお勧めする

サンプル

目次

  1. GraphCMSで簡易サーバー作成
  2. Vue3にVue Apolloの環境を作成
  3. VueからGraphQL を実行(GET)
    ※ POST、PUT、DELETEの サンプルはGitへ

【1】GraphCMSで簡易サーバー作成

GraphCMSはGraphQLでレスポンスを返してくれるCMS
これを使用してDBサーバを作成する

  1. アカウントとプロジェクトの作成
  2. Modelの作成
  3. Fieldの作成
  4. データの追加
  5. Tokenの作成と権限の追加
  6. Content API URLの取得

[1-1] アカウントとプロジェクトの作成

  • Create a new project 設定
    • Template: Blank
    • Project name: test-project
    • Project description: なし
    • Select region: Japan
    • Plan: Free forever
    • Members: -
      • 自分以外にメンバーを追加したい場合のみ設定

[1-2] Modelの作成

  • Schema > MODELS > Add
  • Create Model 設定
    • Display name: Task
    • API ID: Task
    • Plural API ID: Tasks
    • Discription: なし

[1-3] Fieldの作成

  • FieldのTypeを選択する
    • MODELS > task > Add Fields > [Type選択]
  • Create Field 設定1
    • Type: Single line text
    • Display name: title
    • API ID title
  • Create Field 設定2
    • Type: Multi line text
    • Display name: discription
    • API ID discription
  • Create Field 設定3
    • Type: Boolean
    • Display name: task_status
    • API ID task_status

スクリーンショット 2022-08-27 17.00.29.png

[1-4] データの追加

  • Content > DEFAULT VIEWS > [Model Name(Workflow)] > Create Entry

スクリーンショット 2022-08-27 17.02.22.png

[1-5] Tokenの作成と権限の追加

Project Settings > API Access ページでTokenを作成
Project Settings > API Access > Permanent Auth Tokens > Create token

graphcms_token_1.png

作成したTokenに権限を設定する
graphcms_token_permission_1.png
権限を与えるModelを作成したTaskにして追加
graphcms_token_permission_2.png
graphcms_token_permission_3.png

[1-6] Content API URLの取得

  • Content API URL
    • Project Settings > API Access > Endpoints > Content API
      graphcms_api_url.png

【2】Vue3 プロジェクトの作成と設定

  1. Vue3プロジェクトの作成
  2. vue-routerの設定
  3. vue-apolloの設定
  4. eslintの設定

[2-1] Vue3プロジェクトの作成

# yarn create vite <プロジェクト名> --template vue-ts    
yarn create vite vite_ts --template vue-ts 

cd <プロジェクト名>
yarn
yarn dev

作業しやすいようにポートとエイリアスを設定しておく

vite.config.ts

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

export default defineConfig({
  plugins: [vue()],
  server: {
    port: 8888,
  },
  resolve: {
    alias: {
      "~/": `${__dirname}/src/`,
    },
  },
});

tsconfig.jsonにもpathの設定を追加

{
  "compilerOptions": {
    "target": "ESNext",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "lib": ["ESNext", "DOM"],
    "skipLibCheck": true,
    "baseUrl": "./src",
    "paths": {
      "~/*": [
        "./*"
      ]
    }
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

[2-2] vue-routerの設定

yarn add vue-router@4 

以下のファイルを作成

src/App.vue(router-view部分がpageごとに切り替わる)

<template>
  <router-view />
</template>
<style>
table{
  width: 100%;
  border-spacing: 0;
}

table th{
  border-bottom: solid 2px #ccc;
  padding: 10px 0;
}

table td{
  border-bottom: solid 1px #ddd;
  text-align: center;
  padding: 5px 0;
}

input[type="text"] {
  width: 100%;
}

textarea {
  width: 100%;
}

button {
    display: inline-block;
    width: 100%;
    max-width: 100px;
    margin: auto;
    padding: 4px 8px;
    border: none;
    border-radius: 4px;
    background-color: #269dff;
    color: #fff;
    font-size: 12px;
    font-weight: bold;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    cursor: pointer;
    border: 2px solid transparent;
}
button:hover {
  opacity: 0.5;
}
button.small {
  padding: 2px 4px;
  font-size: 10px;
}
button:disabled {
  background-color: #bababa;
  cursor: default;
  opacity: 1;
}
button.outlined:not(:disabled) {
  background-color: #fff;
  border: 1px solid #fb4444;
  color: #fb4444;
}
button.delete:not(:disabled) {
  background-color: #fb4444;
}
button.complete:not(:disabled) {
  background-color: #00b209;
}
</style>

src/router.ts([2-3] vue-apolloの設定時に main.tsで読み込む)

import { createRouter, createWebHistory } from "vue-router";
import Home from "./pages/index.vue";
import getPage from "./pages/get.vue";

const routes = [
  { path: "/", name: "home", component: Home },
  { path: "/get", name: "get", component: getPage },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

[2-3] vue-apolloの設定

  • 追加 plugin
    • "@vue/apollo-option": "^4.0.0-alpha.20"
    • "vue-apollo": "^3.1.0"
    • "graphql-tag": "^2.12.6"
    • "vue-cli-plugin-apollo": "^0.22.2"
yarn add -D graphql-tag vue-cli-plugin-apollo vue-apollo @vue/apollo-option

.env.localに「TokensとContent API URLの取得」で控えた情報を設定

VITE_GRAPHQL_AUTH_TOKEN=[あなたのTOKEN]
VITE_GRAPHQL_HTTP=[あなたのAPI ENDPOINT]
  • main.ts
    • vue-apolloの設定コードを追加
    • vue-routerを読み込み
import "./style.css";
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client/core";
import { createApolloProvider } from "@vue/apollo-option";
import { createApp } from "vue";

import router from "./router";
import App from "./App.vue";

const AUTH_TOKEN = import.meta.env.VITE_GRAPHQL_AUTH_TOKEN || "";
const httpEndpoint =
  import.meta.env.VITE_GRAPHQL_HTTP || "http://localhost:4000/graphql";
const httpLink = new HttpLink({
  uri: httpEndpoint,
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${AUTH_TOKEN}`,
  },
});

/**
 * Create the Apollo client
 */
const cache = new InMemoryCache();
const apolloClient = new ApolloClient({
  cache,
  link: httpLink,
});

/**
 * Create the Apollo provider
 */
const apolloProvider = createApolloProvider({
  defaultClient: apolloClient,
});

/**
 * Add the provider to your app
 */
const app = createApp(App);
app.use(router);
app.use(apolloProvider);

app.mount("#app");

[2-3] eslintの設定

  • 追加 plugin
    • "eslint": "^8.21.0"
    • "eslint-plugin-vue": "^9.3.0"
    • "@vue/eslint-config-typescript": "^11.0.0"
    • "@typescript-eslint/eslint-plugin": "^5.32.0"
    • "@typescript-eslint/parser": "^5.32.0"
yarn add -D eslint eslint-plugin-vue @vue/eslint-config-typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin

eslintの設定ファイル(.eslintrc.yml)を追加

touch .eslintrc.yml

.eslintrc.yml

env:
  browser: true
  es2021: true
extends:
  - 'plugin:vue/vue3-recommended'
  - 'eslint:recommended'
  - '@vue/typescript/recommended'
parser: 'vue-eslint-parser'
parserOptions:
  parser: '@typescript-eslint/parser'
  ecmaVersion: 12
plugins:
  - vue
  - '@typescript-eslint'

Vscodeの拡張機能でVeturを利用してる場合

vue3から利用できる<script setup lang="ts">にVeturは未対応(2022.08.07)
以下手順で拡張機能を変更する

  • Veturを利用するワークスペースでだけ無効化
    • Disable(Workspace)
      スクリーンショット 2022-08-07 16.41.52.png
  • Vue Language Features (Volar)を追加
    スクリーンショット 2022-08-07 16.41.09.png

【3】VueからGraphQLを実行(GET)

設定が終わったので実際に動かしてみる

  1. GraphQL文を書く(GET ワークフローの全ての情報を取得)
  2. Vue Apolloで実行する

[3-1] GraphQL文を書く(GET)

src/constants/task.ts

export const ALL_WORKFLOWS = gql`
query allWorkflows {
    workflows(orderBy: id_ASC) {
      id
      title
      description
      createdAt
    }
  }
`;

titleとdescriptionは自分で設定した項目
idとcreatedAtはpost時に自動で追加される項目

query allWorkflows
「allWorkflows」は好きな名称でよい
このQL文はワークフローの全ての情報を取得するためのものなので「allWorkflows」とした

workflows(orderBy: id_ASC) {
「workflows」はModel名の複数形にすることで「複数データの取得」となる
「orderBy: 項目名_昇順・降順」でソート順を決められる
「id_ASC」はidの昇順、「createdAt_DESC」なら作成した日時順で降順となる

[3-2] Vue Apolloで実行する

apolloの設定はすでにしてあるので
Vueでアポロを使って先ほど作成したQL文章を渡して実行する

src/pages/get.vue

<template>
  <div>
    <table>
      <tr>
        <th width="200">
          ID
        </th>
        <th width="200">
          TITLE
        </th>
        <th width="300">
          DESCRIPTION
        </th>
        <th width="100">
          STATUS
        </th>
      </tr>
      <tr
        v-for="task in tasks"
        :key="task.id"
      >
        <td>{{ task.id }}</td>
        <td>{{ task.title }}</td>
        <td>{{ task.description }}</td>
        <td>{{ task.task_status }}</td>
      </tr>
    </table>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'

import {
  ALL_TASKS,
} from '~/constants/task';

interface task {
  id: string,
  title: string
  description: string
  task_status: boolean
}

interface Data {
  tasks: task[],
}

export default defineComponent({
  name: 'TodoList',
  data(): Data {
    return {
      tasks: [],
    };
  },
  apollo: {
    tasks: ALL_TASKS,
  },
});
</script>

これを実行する

yarn dev

以下のように表示される。
データの取得が行えた。

スクリーンショット 2022-08-27 15.56.37.png

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?