axios vs ofetch 徹底比較

axios の詳細ofetch の詳細
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

axios vs ofetch — HTTP クライアント徹底比較【2025年版】

1. 結論

新規プロジェクトや Nuxt/Nitro エコシステムで開発するなら ofetch が軽量かつモダンな選択肢です。既存の大規模プロジェクトや、インターセプター・進捗監視など豊富な機能が必要なら axios が依然として堅実です。どちらも本番運用に十分な品質を持っており、プロジェクトの要件に合わせて選ぶのが最善です。


2. 比較表

観点axiosofetch
GitHub Stars≈ 106k≈ 4.5k
npm 週間DL数≈ 5,500万≈ 1,000万
バンドルサイズ (minified+gzip)≈ 13 kB≈ 3 kB
TypeScript 対応✅ 同梱型定義✅ ネイティブ TS で記述
ランタイム対応Node.js / ブラウザNode.js / ブラウザ / Workers / Deno / Bun
ベース APIXMLHttpRequest (ブラウザ) / http (Node)Fetch API (全環境統一)
JSON 自動パース
リクエスト/レスポンス インターセプター✅ 組み込み⚠️ onRequest / onResponse フックで実現
リトライ機構❌ 別途プラグイン必要✅ 組み込み(デフォルト1回)
アップロード進捗onUploadProgress❌ Fetch API の制約上なし
リクエストキャンセルAbortController / 旧 CancelTokenAbortController(Fetch 標準)
baseURL 設定✅ (create で設定)
自動エラーハンドリング✅ ステータスコードで rejectFetchError をスロー
学習コスト低(情報量が圧倒的に多い)低〜中(Fetch 経験者なら容易)
メンテナーコミュニティUnJS (Nuxt コアチーム)

3. それぞれの強み

axios の強み

  • 圧倒的な情報量とエコシステム Stack Overflow の回答数、ブログ記事、サードパーティプラグイン(axios-retryaxios-mock-adapter など)が非常に豊富です。チームに新しいメンバーが入っても学習リソースに困りません。

  • インターセプターの柔軟性 リクエスト/レスポンスの前後処理をチェーンで登録でき、認証トークンの付与やグローバルエラーハンドリングを宣言的に記述できます。

  • アップロード/ダウンロード進捗の監視 onUploadProgress / onDownloadProgress コールバックが組み込みで提供されており、ファイルアップロード UI の実装が容易です。

  • ブラウザ互換性 内部で XMLHttpRequest を使用するため、Fetch API 未対応の古い環境でもポリフィルなしで動作します。

ofetch の強み

  • 圧倒的な軽量さ gzip 後わずか約 3 kB。バンドルサイズに敏感な SPA やエッジワーカーに最適です。

  • Fetch API ネイティブ Web 標準の Fetch API をラップしているため、Cloudflare Workers・Deno・Bun など あらゆるモダンランタイムで統一的に動作 します。

  • 組み込みリトライ ネットワークエラーや 5xx レスポンスに対して自動リトライが組み込まれており、追加パッケージが不要です。

  • UnJS エコシステムとの親和性 Nuxt 3 / Nitro の内部 HTTP クライアントとして採用されており、$fetch としてゼロコンフィグで利用できます。

  • 型推論の優秀さ TypeScript でゼロから書かれており、ジェネリクスによるレスポンス型の推論が自然です。


4. コード例で比較

4-1. 基本的な GET リクエスト

axios

import axios from "axios";

interface User {
  id: number;
  name: string;
  email: string;
}

// axios.get<T> の T は response.data の型になる
const { data: user } = await axios.get<User>(
  "https://jsonplaceholder.typicode.com/users/1"
);

console.log(user.name); // "Leanne Graham"

ofetch

import { ofetch } from "ofetch";

interface User {
  id: number;
  name: string;
  email: string;
}

// ofetch<T> の T は返り値そのものの型になる(data ラッパーなし)
const user = await ofetch<User>(
  "https://jsonplaceholder.typicode.com/users/1"
);

console.log(user.name); // "Leanne Graham"

ポイント: axios は response.data にアクセスする必要がありますが、ofetch はパース済みデータを直接返します。


4-2. POST リクエスト(JSON 送信)

axios

import axios from "axios";

interface CreatePostBody {
  title: string;
  body: string;
  userId: number;
}

interface Post extends CreatePostBody {
  id: number;
}

const { data: newPost } = await axios.post<Post>(
  "https://jsonplaceholder.typicode.com/posts",
  {
    title: "axios vs ofetch",
    body: "比較記事を書いています",
    userId: 1,
  } satisfies CreatePostBody
);

console.log(newPost.id); // 101

ofetch

import { ofetch } from "ofetch";

interface CreatePostBody {
  title: string;
  body: string;
  userId: number;
}

interface Post extends CreatePostBody {
  id: number;
}

const newPost = await ofetch<Post>(
  "https://jsonplaceholder.typicode.com/posts",
  {
    method: "POST",
    body: {
      title: "axios vs ofetch",
      body: "比較記事を書いています",
      userId: 1,
    } satisfies CreatePostBody,
  }
);

console.log(newPost.id); // 101

ポイント: axios は axios.post() のようにメソッド別のショートハンドがあります。ofetch は method オプションで指定するスタイルです。


4-3. インスタンス生成と共通設定

axios

import axios from "axios";

const api = axios.create({
  baseURL: "https://api.example.com/v1",
  timeout: 10_000,
  headers: {
    Authorization: "Bearer my-token",
  },
});

// インターセプターで共通エラーハンドリング
api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (axios.isAxiosError(error) && error.response?.status === 401) {
      console.error("認証エラー: トークンを更新してください");
      // リフレッシュトークン処理など
    }
    return Promise.reject(error);
  }
);

const { data } = await api.get("/users/me");

ofetch

import { ofetch, FetchError } from "ofetch";

const api = ofetch.create({
  baseURL: "https://api.example.com/v1",
  timeout: 10_000,
  headers: {
    Authorization: "Bearer my-token",
  },
  retry: 2, // 5xx / ネットワークエラー時に最大2回リトライ

  async onResponseError({ response }) {
    if (response.status === 401) {
      console.error("認証エラー: トークンを更新してください");
      // リフレッシュトークン処理など
    }
  },
});

const user = await api("/users/me");

ポイント: どちらもファクトリ関数でインスタンスを生成できます。axios はインターセプターを use() で後付けし、ofetch はオプションオブジェクト内にフックを宣言します。


4-4. エラーハンドリング

axios

import axios, { AxiosError } from "axios";

try {
  await axios.get("https://api.example.com/not-found");
} catch (error) {
  if (axios.isAxiosError(error)) {
    const axiosErr = error as AxiosError<{ message: string }>;
    console.error("ステータス:", axiosErr.response?.status);       // 404
    console.error("メッセージ:", axiosErr.response?.data?.message); // "Not Found"
  } else {
    throw error; // axios 以外のエラーは再スロー
  }
}

ofetch

import { ofetch, FetchError } from "ofetch";

try {
  await ofetch("https://api.example.com/not-found");
} catch (error) {
  if (error instanceof FetchError) {
    console.error("ステータス:", error.response?.status);        // 404
    console.error("メッセージ:", error.data?.message);           // "Not Found"
  } else {
    throw error;
  }
}

ポイント: axios は isAxiosError() 型ガード、ofetch は標準の instanceof で判定します。ofetch の FetchErrorerror.data にパース済みレスポンスボディが入るため、ワンステップ少なくアクセスできます。


4-5. アップロード進捗の監視(axios のみ)

import axios from "axios";

const formData = new FormData();
formData.append("file", selectedFile);

const { data } = await axios.post("/api/upload", formData, {
  headers: { "Content-Type": "multipart/form-data" },
  onUploadProgress(progressEvent) {
    const percent = Math.round(
      (progressEvent.loaded * 100) / (progressEvent.total ?? 1)
    );
    console.log(`アップロード進捗: ${percent}%`);
  },
});

注意: ofetch(Fetch API)にはアップロード進捗を監視する標準的な仕組みがありません。この機能が必須の場合は axios を選択するか、XMLHttpRequest を直接使う必要があります。


5. どちらを選ぶべきか — ユースケース別ガイド

ユースケース推奨理由
Nuxt 3 / Nitro プロジェクトofetchフレームワーク内部で採用済み。$fetch として統合されている
Cloudflare Workers / Deno / BunofetchFetch API ベースのため追加設定なしで動作する
バンドルサイズを極限まで削りたい SPAofetchgzip 後 ≈ 3 kB と圧倒的に軽量
ファイルアップロードで進捗バーが必要axiosonUploadProgress が組み込みで提供されている
既存の大規模 React/Vue プロジェクトaxios移行コストを考慮。情報量・プラグインが豊富
複雑なインターセプターチェーンaxios複数のインターセプターを順序付きで管理しやすい
自動リトライが欲しいofetch追加パッケージ不要で組み込みリトライが使える
レガシーブラウザ対応が必要axiosXMLHttpRequest ベースのため Fetch ポリフィル不要
チームに Fetch API 経験者が多いofetch標準 API の薄いラッパーなので学習コストが低い

6. まとめ

axiosofetch
一言で言うと成熟した万能選手軽量モダンな新鋭

axios は 10 年以上の実績と膨大なエコシステムを持ち、「困ったら axios」と言えるほどの安心感があります。一方 ofetch は Web 標準の Fetch API を土台に、リトライ・型推論・マルチランタイム対応といったモダンな要件を最小限のサイズで満たします。

どちらも活発にメンテナンスされており、品質面での優劣はありません。プロジェクトの技術スタック・チームの経験・必要な機能を軸に選択すれば、どちらを選んでも後悔することはないでしょう。