Skip to content

HttpClientModuleが非推奨になった理由と代替手段

問題の核心

Angular 18から従来のHttpClientModule非推奨になりました。モジュールベースのプロジェクトで次のように使用すると警告が発生します:

typescript
@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule, // 非推奨
    ...
  ],
})
export class AppModule {}

非推奨の主な理由は:

  1. モジュール方式が冗長HttpClientModuleは内部でprovideHttpClient()関数を実行しているだけ
  2. スタンドアロンAPIとの統一:関数型プロバイダーを標準化する設計方針
  3. 誤用の削減:モジュールと関数プロバイダーの併用による混乱を解消

適切な代替方法

1. 基本設定 (provideHttpClient())

HttpClientModuleの完全な代替としてprovideHttpClient()を利用:

typescript
import { provideHttpClient } from '@angular/common/http';

// モジュールベースプロジェクトの場合
@NgModule({
  providers: [provideHttpClient()], // モジュールのimportsではなくprovidersに追加
})
export class AppModule {}

// スタンドアロンコンポーネントの場合 (Angular 18デフォルト)
export const appConfig: ApplicationConfig = {
  providers: [provideHttpClient()],
};

重要な変更点

  • @NgModuleimportsから削除
  • providers配列に追加

2. Fetch APIの利用(オプション)

XHRベースのデフォルト通信を変更する場合:

typescript
providers: [
  provideHttpClient(
    withFetch() // Fetch APIを使用
  )
]

3. インターセプター設定

認証インタセプターなどのカスタマイズ例:

typescript
providers: [
  provideHttpClient(
    withInterceptors([authInterceptor])
  )
]

実装コード (auth.interceptor.ts):

typescript
import { HttpInterceptorFn } from '@angular/common/http';

export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = sessionStorage.getItem('JWT');
  if (token) {
    const authReq = req.clone({
      headers: req.headers.set('Authorization', `Bearer ${token}`)
    });
    return next(authReq);
  }
  return next(req);
};

移行時に発生するエラーと対応

タイプエラー Type 'EnvironmentProviders' is not assignable to type 'Provider'

  • 原因:コンポーネント内でHttpClientModuleをインポート
  • 解決策:該当コンポーネントからHttpClientModuleの参照を完全削除

No provider for HttpClient

  • 原因
    • モジュールのprovidersprovideHttpClient()追加漏れ
    • app.config.tsbootstrapApplicationに渡し忘れ
  • 解決策
typescript
// main.ts
bootstrapApplication(
  AppComponent,
  appConfig // 構成情報を明示的に渡す
);

推奨される設計パターン

サービスレイヤー構成例 (user.service.ts)

typescript
import { HttpClient } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class UserService {
  constructor(private http: HttpClient) {}

  fetchUsers() {
    return this.http.get<User[]>('/api/users');
  }
}

app.config.ts 標準構成

typescript
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient, withInterceptors } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([loggingInterceptor]) // 複数インターセプター可
    ),
    UserService // サービスを直接提供可能
  ]
};

非推奨の背景と公式方針

Angularの公式ソースコードでは、HttpClientModuleが単なるラッパーである事が明示されています:

typescript
@NgModule({
  providers: [provideHttpClient(withInterceptorsFromDi())],
})
export class HttpClientModule {} // 実質空クラス

移行のメリット

  1. ツリーシェイキング効率化
  2. スタンドアロン/モジュール構造の統一
  3. 機能拡張の容易さ (withInterceptors等の拡張関数追加)

公式ドキュメントはHTTPガイドで詳細を解説しています。