12k
All articles

Fetch では得られない、Axios が今なお提供してくれるもの

Axios vs Fetch: インターセプター、自動HTTPエラー処理、共有インスタンス、アップロード進捗、タイムアウトでAxiosが有利な点を整理します。

OpenReplay Team
OpenReplay Team
Fetch では得られない、Axios が今なお提供してくれるもの

Fetch API は大きく成熟しました。すべてのモダンブラウザに組み込まれており、Node.js では v18 以降 Undici を介してネイティブで利用可能となり、JSON の処理、リクエストのキャンセル、ストリーミングにも対応しています。多くのフロントエンドの API リクエストには、これで十分です。

それでもなぜ、チームは依然として Axios を選ぶのでしょうか。それは習慣からではなく、Axios が Fetch では開発者に委ねられている特定の DX 上の課題を解決し続けているからです。実際にその差が表れる箇所を見ていきましょう。

重要なポイント

  • Fetch は 4xx や 5xx のレスポンスでも成功として解決されるため、すべてのリクエストで手動の response.ok チェックが必要になります。
  • Axios のインターセプターは、認証トークン、ロギング、エラー正規化といった横断的関心事を、リクエストごとのボイラープレートなしで一元管理できます。
  • axios.create() による共有設定は、異なるベース URL、ヘッダー、タイムアウトを必要とする複数の API を扱う際に作業を簡素化します。
  • アップロード進捗の追跡や組み込みのタイムアウトオプションは、Fetch がネイティブでは対応できない、Axios 独自の機能のままです。
  • HTTP の用途が最小限の小規模プロジェクトでは、依存関係ゼロのデフォルトとして Fetch が適切な選択です。

Axios と Fetch:本当の違いはどこにあるか

1. デフォルトで機能する HTTP エラーハンドリング

Fetch はネットワーク障害でしか reject されません。404500 のレスポンスは正常に解決されるため、毎回自分で response.ok を確認する必要があります。

// Fetch — 手動でチェックする必要がある
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
const data = await res.json();

// Axios — デフォルトで 4xx/5xx を自動的に reject する
const { data } = await axios.get('/api/user');

数十のエンドポイントを持つ大規模アプリケーションでは、この手動チェックが繰り返しのボイラープレートになります。Axios はそのほとんどをデフォルトで取り除いてくれます。


2. 組み込みのリクエスト/レスポンス インターセプター

これは多くの開発者が Axios を選ぶ際に挙げる機能です。インターセプターを使えば、認証トークン、ロギング、エラー正規化といったロジックを、個々のリクエストに手を加えることなく、一度だけグローバルに付与できます。

axios.interceptors.request.use(config => {
  config.headers.Authorization = `Bearer ${getToken()}`;
  return config;
});

axios.interceptors.response.use(
  response => response,
  error => {
    if (error.response?.status === 401) redirectToLogin();
    return Promise.reject(error);
  }
);

Fetch では、fetch() をカスタム関数でラップすれば似たことを再現できます。しかしそのラッパーはコンポーザブルでもスタッカブルでもなく、自分で保守し続けなければなりません。


3. Axios インスタンスによる設定の共有

Axios では、ベース URL、ヘッダー、タイムアウトを事前設定した独立したインスタンスを作成できます。これは、アプリが複数の API と通信する場合に本当に便利なパターンです。

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 8000,
  headers: { 'X-App-Version': '2.1.0' },
});

Fetch でこれをきれいに再現するには、ラッパークラスやファクトリ関数が必要になります。実現は可能ですが、自分で背負うべき範囲が広がります。


4. アップロード進捗のトラッキング

Fetch には今もブラウザで標準化されたネイティブのアップロード進捗 API がありません。Axios は onUploadProgress を直接公開しており、ブラウザでは内部的に XMLHttpRequest によって支えられています。

await axios.post('/upload', formData, {
  onUploadProgress: e => {
    if (e.total) {
      console.log(`${Math.round((e.loaded / e.total) * 100)}%`);
    }
  },
});

Fetch のみの構成でアップロード進捗が必要であれば、結局生の XMLHttpRequest に戻ることになります。これは明らかな後退です。


5. AbortController のボイラープレートなしのタイムアウト設定

Axios は timeout オプションを直接受け付けます。Fetch では AbortControllersetTimeout を手動で組み合わせる必要があり、動作はしますが冗長になります。

// Axios
await axios.get('/api/data', { timeout: 5000 });

// Fetch の同等コード
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), 5000);
try {
  const res = await fetch('/api/data', { signal: controller.signal });
} finally {
  clearTimeout(id);
}

モダンな環境では AbortSignal.timeout() もサポートされており、これによりかなり短く書けます。ブラウザ対応状況も現在は広く整っています。


簡易比較:Axios の機能 vs Fetch API

機能FetchAxios
HTTP エラーの reject手動の response.ok チェックデフォルトで自動
インターセプターカスタムラッパーが必要組み込み
共有インスタンス手動のファクトリパターンaxios.create()
アップロード進捗ネイティブ非対応onUploadProgress
リクエストタイムアウトAbortController + setTimeouttimeout オプション
バンドルサイズ0 KB(ネイティブ)gzip で約 15 KB

まとめ

Fetch は決して不十分ではありません。シンプルな JavaScript の HTTP クライアント — 少数のエンドポイント、共有の認証ロジックなし、アップロード進捗なし — であれば、Fetch が適切なデフォルトです。依存関係もなく、オーバーヘッドもありません。

しかし、フロントエンドの API リクエストが複雑化するにつれて、Axios はその価値を発揮します。インターセプター、共有インスタンス、自動エラーハンドリング、アップロード進捗 — これらは必要になるまで気づかない機能ですが、いざ必要になれば、自前で組むのではなく組み込みで備わっていてほしいと感じるはずです。それこそが、Axios が今なお提供してくれるものです。

FAQ

Fetch がすべてのモダンブラウザと Node.js に組み込まれている今も、Axios を追加する価値はありますか?

プロジェクトの複雑さによります。シンプルなリクエストが少数あるだけなら、Fetch で十分であり、依存関係を避けられます。共有認証、一元化されたエラーハンドリング、複数の API クライアント、アップロード進捗の要件があるアプリケーションでは、Axios は自前で再実装する必要のある大量のボイラープレートを節約してくれます。

Axios のインターセプターをカスタムの Fetch ラッパーで再現できますか?

部分的には可能です。fetch を関数でラップしてヘッダーを注入したりエラーを処理したりはできますが、Axios のインターセプターが持つスタッカブルでコンポーザブルな性質は失われます。新しい関心事ごとにラッパーを直接修正する必要があり、複数の独立したインターセプターを連鎖させるのは扱いにくくなります。これを試みた多くのチームは、最終的に Axios のより小規模でテストの少ないバージョンを再構築することになります。

Axios は Node.js でもブラウザと同じようにアップロード進捗をサポートしていますか?

完全に同じではありません。Axios は Node.js でもアップロードとダウンロードの進捗をサポートしますが、Node は XMLHttpRequest を使わないため実装はブラウザと異なります。ブラウザの進捗イベントは一般的により滑らかでより細かい粒度を持つ一方、Node.js のアップロード — 特に FormData のアップロード — ではアダプタやランタイムによって制限がある場合があります。

Axios の代わりに ky や got などの代替手段はどうですか?

どちらも優れています。Ky は Fetch ベースの小さなラッパーで、軽量さを保ちつつリトライ、フック、タイムアウトを追加します。Got は機能豊富ですが Node 専用です。Axios が依然として人気なのは、ブラウザと Node の両環境で同一の API で動作し、エコシステムのサポートが広く、多くの JavaScript 開発者にとって馴染みがあるためです。

Open-source session replay

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.