intro-to-graphql/README.md
2021-05-29 07:33:09 +09:00

9.6 KiB

marp paginate
true true

GraphQL概論

WebDINO Japan エンジニア 渡邉浩平 w:200


GraphQLとは

https://graphql.org


GraphQLとはAPIのクエリ言語

サーバーへの問い合わせ (GraphQL Query)

query {
  pokemon(name: "Pikachu") {
    classification
  }
}

サーバーからの応答 (JSON)

{
  "data": {
    "pokemon": {
      "classification": "Mouse Pokémon"
    }
  }
}

https://graphql-pokemon2.vercel.app


歴史

  • 2012年 Facebookによる開発
  • 2015年 オープンソース化
  • 2019年 GraphQL Foundationに移管

オープンソースな仕様になっており、自由に貢献可能


主な仕様

GraphQL以外の身近な言語の例:


何でないか

  • データベースではない
  • JavaScriptではない

なぜGraphQLを使うのか

  1. 単一リクエスト
  2. 型システム
  3. 開発ツール

1. 単一リクエスト

効率的なデータ読み込み

FacebookがGraphQLを開発した理由は、モバイルネイティブアプリへの移行のため スマホの普及に伴う低速、省電力なデバイスの利用の増加が背景

RESTは複数のエンドポイントへの問い合わせを行うという典型的な課題がある クライアントのデータ取得の効率やデータの表現の都合で似たような振る舞いのAPIを作りがち

GraphQLは単一のリクエストで指定したデータを取得可能 オーバーフェッチを最小限に抑え、サーバーへのラウンドトリップを少なくする


REST

h:600 REST https://hasura.io/learn/graphql/intro-graphql/graphql-vs-rest/


GraphQL

h:600 GraphQL https://hasura.io/learn/graphql/intro-graphql/graphql-vs-rest/


2. 型システム

さまざまなフロントエンド環境のサポート

単一APIの構築と正確なデータ構造の維持 クライアントアプリケーションを実行するフロントエンドフレームワークとプラットフォームの多様化が背景


GraphQL Schema

"""ポケモンを表します"""
type Pokemon {
  """このオブジェクトのID"""
  id: ID!

  """このポケモンの全国図鑑No."""
  number: String

  """このポケモンの名前"""
  name: String

  """このポケモンの重さの最大と最小"""
  weight: PokemonDimension

  """このポケモンの高さの最大と最小"""
  height: PokemonDimension

  """このポケモンの分類"""
  classification: String

  # ...
}

"""ポケモンを表します"""
type Pokemon {
}

"""ポケモンの寸法を表します"""
type PokemonDimension {
}

オブジェクトの種類


"""ポケモンを表します"""
type Pokemon {
  """このオブジェクトのID"""
  id: ID!

  """このポケモンの名前"""
  name: String

  """このポケモンの分類"""
  classification: String

  """このポケモンの高さの最大と最小"""
  height: PokemonDimension
}

オブジェクトに含まれるフィールド


特定のプログラミング言語に依存しない

// JavaScript
const pokemonQuery = `{ pokemon(name: "Pikachu") { classification } }`;

fetch(`http://example/?${new URLSearchParams({ query: pokemonQuery })}`)
  .then(r => r.json())
  .then(({ data }) => console.log(data?.pokemon?.classification));
// => "Mouse Pokémon"
// Kotlin
val response = apolloClient.query(pokemonQuery).await()
Log.d(response?.data?.pokemon?.classification)
// Swift
apollo.fetch(query: pokemonQuery) { result in
  guard let data = try? result.get().data else { return }
  print(data.pokemon?.classification)
}

https://www.apollographql.com


3. 開発ツール

短期間での開発

クライアントアプリケーションの設計変更に対応するためのツールが提供されている 継続的デプロイ (CD) が背景


IDE - GraphiQL

h:600 GraphiQL

https://github.com/graphql/graphiql


GraphQL Code Generator

コードの生成

$ graphql-codegen

使う

import { usePokemonQuery } from "./generated";

export default () => {
  const { data } = usePokemonQuery();
  return data?.pokemon?.classification;
};

React, Vue, Kotlin, etc.

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


Hasura

GraphQLサーバー 接続したデータベースを自動的にGraphQL APIとして提供

https://hasura.io


まとめ

  • GraphQLとはデータを問い合わせるクエリ言語仕様と周辺技術
  • 単一リクエスト/型システム/開発ツール

GraphQLをもっと知る

使うための知識を深める


GraphQL Operation

3種類の操作

  • query - 読み取り
  • mutation - 書き込み
  • subscription - イベントストリーム

1つのリクエストに複数の操作を含めることが可能


Query - データの取得


基本的な構文

query {
  pokemon(name: "Pikachu") {
    classification
  }
}

query … 操作 name … 引数 "Pikachu" … 値 pokemon, classification … フィールド


子孫関係

query {
  pokemon(name: "Pikachu") {
    classification
    height {
      minimum
      maximum
    }
  }
}

height フィールドの中の minimum, maximum フィールド


変数を使ったqueryの再利用

query ($name: String!) {
  pokemon(name: $name) {
    classification
    height {
      minimum
      maximum
    }
  }
}

+

{
  "name": "Pikachu"
}

$name … 変数 String! … 型


操作を名付ける

query fetchPikachu {
  pokemon(name: "Pikachu") {
    classification
  }
}

fetchPikachu … 操作名


フィールドを名付ける

query {
  pikachu: pokemon(name: "Pikachu") {
    classification
  }
}

pikachu … エイリアス


フラグメント

fragment dimension on PokemonDimension {
  minimum
  maximum
}

query {
  pokemon(name: "Pikachu") {
    classification
    height {
      ...dimension
    }
    weight {
      ...dimension
    }
  }
}

dimension … フラグメント


ディレクティブ

query ($showClassification: Boolean!) {
  pokemon(name: "Pikachu") {
    classification @include(if: $showClassification)
  }
}

+

{
  "showClassification": true
}

@include … ディレクティブ


まとめ

  • 3種類の操作
  • Queryによるデータの取得

後付


より理解を深めるための知識


何を話していないか


セキュリティ

セキュリティの懸念事項は一般的なWebサービスと同様に存在


認証・認可

GraphQL仕様に含まないので一般的なWebの認証・認可の設計と同様に行う


キャッシュ

HTTP GETメソッドによる一般的なHTTP キャッシュに加え、GraphQLではグローバルなオブジェクトの識別子の宣言によるキャッシュが存在


JSON Serialization

GraphQL Value JSON Value
Map Object
List Array
Null null
String/Enum Value String
Boolean true or false
Int/Float Number

https://spec.graphql.org/June2018/#sec-JSON-Serialization