てらブログ

てらブログ

日々の学習の備忘録

graphql-request, axios, fetch関数、何が違うのか比較検討してみた

目的

graphql-requestがプロジェクトで使用されることになったが、そもそも知らなかったので簡単に調べてみた。
また、他の選択肢とどう違うのかが気になったので、axios, fetch関数の特徴とメリットデメリットについて考えてみた。

graphql-requestとは

GraphQLクエリやミューテーションを送るための最もシンプルなFetch APIラッパー。npmパッケージとして提供されており、node.jsまたはブラウザにインストールして使用することができる。

主な特徴

  • フェッチのための最も小さなフレームワーク
  • 依存関係が少ない
  • PromiseベースのAPI(async/awaitと互換性あり)
  • サーバーのエラーメッセージをそのままスローする
  • HTTPとHTTPSの両方に対応
  • ミドルウェアのサポート(ログ、エラーハンドリング、etc.)

参照:
graphql-request - npm

使用例

シンプルな例

下記のコードでは、特定の映画(ここでは"Inception")のリリース日とその出演者の名前を問い合わせている。graphql-requestはPromiseを返すので、async/awaitを使用して結果を受け取る。
また、より複雑なクエリやミューテーション、またはヘッダー情報を含むリクエストなども同じAPIを通じて送信することができる。

const { request, gql } = require('graphql-request')

const endpoint = 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn'

const query = gql`
  {
    Movie(title: "Inception") {
      releaseDate
      actors {
        name
      }
    }
  }
`

const fetchData = async () => {
  try {
    const data = await request(endpoint, query)
    console.log(data)
  } catch (error) {
    console.error(error)
  }
}

fetchData()
react-queryと組み合わせて使用してみる
import React from 'react'
import { useQuery } from 'react-query'
import { request, gql } from 'graphql-request'

const fetchMovie = async () => {
  const query = gql`
    {
      Movie(title: "Inception") {
        releaseDate
        actors {
          name
        }
      }
    }
  `
  const data = await request('https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', query)
  return data.Movie
}

export default function App() {
  const { isLoading, error, data } = useQuery('movieData', fetchMovie)

  if (isLoading) return 'Loading...'

  if (error) return `An error has occurred: ${error.message}`

  return (
    <div>
      <h1>{data.title}</h1>
      <p>{data.releaseDate}</p>
      <ul>
        {data.actors.map((actor, index) => (
          <li key={index}>{actor.name}</li>
        ))}
      </ul>
    </div>
  )
}

axios・fetchで置き換えてみる

axiosの場合

import axios from 'axios'
import { useQuery } from 'react-query'

const fetchMovie = async () => {
  const query = `
    {
      Movie(title: "Inception") {
        releaseDate
        actors {
          name
        }
      }
    }
  `
  const { data } = await axios.post('https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', { query })
  return data.data.Movie
}

fetch関数の場合

import { useQuery } from 'react-query'

const fetchMovie = async () => {
  const query = `
    {
      Movie(title: "Inception") {
        releaseDate
        actors {
          name
        }
      }
    }
  `
  const res = await fetch('https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ query }),
  })
  const json = await res.json()
  return json.data.Movie
}

このコードだけ見るとそんなに大差がないように感じる。

それぞれのメリデメ

graphql-request

メリット
シンプルで直感的なAPIを提供し、GraphQLクエリやミューテーションを手軽に送信できる。
ラッパーが薄く、依存関係が少ないため、パフォーマンスのオーバーヘッドがほとんどない。

デメリット
GraphQLのクエリを送信する基本的な機能しか提供しないため、より高度な機能(例えば、自動リトライ、タイムアウト設定など)が必要な場合には適していない。

axios

メリット
axiosは、ブラウザとNode.jsの両方で動作する非常に人気のあるHTTPクライアント。リクエストとレスポンスのインターセプター、リクエストのキャンセル、JSONデータの自動変換など、強力な機能を備えている。
HTTPリクエストのタイムアウトを設定するなど、高度なカスタマイズが可能。

デメリット
axiosは、フェッチAPIをラップしたライブラリなので、フェッチAPIが利用可能な場合(モダンなブラウザやnode-fetchを使用するNode.jsの環境)は、その利用を検討する方が良いかもしれない。
GraphQLに特化したライブラリではないため、GraphQLのクエリを手軽に送信するための特別な機能は提供していない。

fetch

メリット
fetchは、ブラウザの組み込みAPIであり、外部の依存関係なしにHTTPリクエストを行うことができる。

デメリット
一部の古いブラウザ(特にIE)では、fetch APIはネイティブにはサポートされていない(ただし、ポリフィルを使用することで解決可能)。
レスポンスのエラーハンドリングがやや不便で、HTTPエラーステータスを自動的に拾ってエラーを投げてくれないため、それを手動でチェックする必要がある。
axiosと比較して高度な機能が欠けている(リクエストのキャンセルやタイムアウトの設定など)。