lacolaco's marginalia

Reading and Developing

Angular: provideHttpClient はもう不要(でも必要)

Angularアドベントカレンダー 25日目です。参加いただいた皆さんありがとうございました!コミュニティを代表して超感謝です。気づかないうちに2枚目まであふれており、派手さはなくともAngularコミュニティのふつふつと沸き立つ熱を感じる2025年末でした。

さて、25日の担当で何を書くかというと、仰々しい締めの内容ではなく、Angular v21のTipsです。クリスマスプレゼントだと思ってください。


実はAngular v21から、HttpClientが最初からルートスコープで提供されるようになっています。つまり、providedIn: 'root'になっているということです。

これが意味することは、AngularアプリケーションでHttpClientを使うのにわざわざprovideHttpClient()でプロバイダーの用意をしなくてよいということです。次のコードはHttpClientを利用するAppコンポーネントを使ってアプリケーションを起動していますが、どこにも追加のDIプロバイダーがありません。これだけで動きます。

@Component({
  selector: 'app-root',
  template: `
    @for(user of users(); track user.id) {
      <p>{{ user.id }}: {{ user.name }}</p>
    }
  `,
})
export class App {
  readonly #http = inject(HttpClient);
  readonly users = signal<User[]>([]);

  ngOnInit() {
    this.#http
      .get<User[]>('https://jsonplaceholder.typicode.com/users')
      .subscribe((users) => {
        this.users.set(users);
      });
  }
}

bootstrapApplication(App);

httpResourceを使い HttpClientを直接呼び出さないケースでも、内部ではHttpClientに依存しているため、v20まではプロバイダーが必要でしたが、これも不要になりました。

@Component({
  selector: 'app-root',
  template: `
    @for(user of users(); track user.id) {
      <p>{{ user.id }}: {{ user.name }}</p>
    }
  `,
})
export class App {
  readonly #usersResource = httpResource<User[]>(
    () => `https://jsonplaceholder.typicode.com/users`
  );
  readonly users = computed(() => this.#usersResource.value());
}

bootstrapApplication(App);

ちょっとコードが減りました。めでたしめでたし

provideHttpClientは引き続き必要

原理的には明示的なプロバイダーは不要になりましたが、実用上は引き続き必要です。なぜかというと大抵のプロジェクトではインターセプター機能を利用しているからです。

HttpClientのインターセプター機能を利用するにはprovideHttpClientのオプションが必要です。関数を渡すwithInterceptorsを使うにせよ、DI経由でクラスを渡すwithInterceptorsFromDiを使うにせよ、どちらにしろHttpClientの明示的な設定がなければ使えません。

provideHttpClient関数に何らかの引数を渡して設定を加えている場合は、それを消すことはできません。今までどおり残しておきましょう。

プロトタイプの簡略化

実用的には消せませんが、それでもAngularアプリケーションをサクッと作ってプロトタイピングする際に、HTTPリクエストを送る機能を実装するためのステップが減るのは明確な利点です。特にAngularチームはSignalベースのhttpResourceを推していきたいところですから、設定ゼロのデフォルト状態で機能を使えるようにしたかったのでしょう。

テストにおける利点

provideHttpClientが不要になったことは実はユニットテストにおいて地味に便利です。HttpClienthttpResourceへの依存があるコンポーネントやサービスをTestBedでテストするとき、そのテストでHTTPリクエストが発生しないとしても依存関係を解決するためだけにprovideHttpClientをセットせずに済みます。

とはいえこのケースは v21からデフォルト設定となった @angular/build:unit-test によるテスト実行(Vitestランナー)であれば、angular.jsonprovidersFileにテスト用のグローバル設定を指定できるため、利点としてはありがたみが薄くなりそうです。

// src/test-providers.ts
import { Provider } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
const testProviders: Provider[] = [
  provideHttpClient(),
  provideHttpClientTesting(),
];
export default testProviders;

まとめ

Angular v21からHttpClientprovidedIn: 'root'になったことで、プロトタイピングやシンプルなHTTPリクエストの実装がより簡単になりました。実用上はインターセプターの設定のためにprovideHttpClientを使い続けることになりますが、設定が不要なデフォルト状態でも動作するという改善は、Angularの学習コストを下げる上でも意味のある変更だと言えるでしょう。

それではみなさん良いお年を!