Angular 19におけるAPP_INITIALIZERの非推奨と移行方法
問題点
Angular 18から19へアップグレードする際、APP_INITIALIZER
の使用が非推奨となり、新しいprovideAppInitializer
関数への移行が必要です。しかし自動マイグレーションで変換されたコードを実行すると、次のエラーが発生します:
Uncaught RuntimeError: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`.
この問題は主に、inject()
を適切な依存性注入コンテキストで呼び出していないことが原因です。Angular 19では初期化ロジックの登録方法が変更されましたが、自動移行ツールが完全に正しいコードを生成しないケースがあります。
解決方法
🛠 方法1: 初期化関数のラッピング(手動修正)
エラーを解決する最も直接的な方法は、初期化関数をラムダ(アロー関数)でラップしinject()
の呼び出しを「依存性注入コンテキスト」内で実行することです:
// 修正後のコード
providers: [
provideAppInitializer(() => initializeApp1(inject(AuthService)))
]
重要なポイント
() =>
で関数をラップすることで安全な注入コンテキストを生成inject(Service)
で既存サービスのインスタンスを注入可multi: true
オプションは不要(自動管理)
実装パターン例
const initializeApp = () => {
const configService = inject(ConfigService);
return configService.loadConfig();
};
// プロバイダ登録
providers: [provideAppInitializer(initializeApp)];
⚙️ 方法2: 公式マイグレーションコマンドの実行(推奨)
Angular CLIが提供する専用マイグレーションコマンドで完全な修正を行います:
ng update @angular/core --name provide-initializer
アップデート中に以下のプロンプトが表示された場合:
** Optional migrations of package '@angular/core' **
This package has 1 optional migration:
❯ Replaces APP_INITIALIZER, ENVIRONMENT_INITIALIZER & PLATFORM_INITIALIZER
respectively with provideAppInitializer, provideEnvironmentInitializer & providePlatformInitializer.
このコマンドがAPP_INITIALIZER
を適切な形式のprovideAppInitializer
に自動変換します。
注意
- CLIの初期アップグレード(
ng update @angular/core@19
)時には同時に実行されない - 明示的に追加コマンドを実行する必要あり
🔧 複雑な依存関係の対応例
複数の依存関係が必要なケースや初期化ロジックが複雑な場合は関数をネストします:
provideAppInitializer(() => {
const authService = inject(AuthService);
const configService = inject(ConfigService);
return () => {
return authService.init().pipe(
switchMap(() => configService.load())
);
};
}),
エラーの根本原因
NG0203
エラーはinject()
関数が不適切なコンテキストで呼び出された場合に発生します。Angular 19のprovideAppInitializer
は:
- 初期化関数を依存性注入コンテキスト内で実行
- 無名関数ではない既存のファクトリ関数を直接渡すとコンテキスト喪失
- 関数ラッピングがコンテキスト境界を確立
元のAPP_INITIALIZER
のdeps
オプションは不要に:
- { provide: APP_INITIALIZER, useFactory: ... }
+ provideAppInitializer(...) // 簡潔な関数ベースAPI
内部構造の変更点(Advanced)
Angular 18 | Angular 19 |
---|---|
APP_INITIALIZER トークン | provideAppInitializer() 関数 |
multi: true 管理 | 内部で複数登録自動対応 |
明示的deps 指定 | inject() による暗黙的解決 |
ベストプラクティス
公式マイグレーションを優先
ng update --name provide-initializer
を最初に実行初期化関数の軽量化
typescript// ❌ 重い処理 provideAppInitializer(() => fetchBigData()) // ✅ 最小限に保つ provideAppInitializer(() => initializeEssentialConfig())
非同期処理の扱い
関数がPromiseを返す場合、Angularはその解決を待機:typescriptprovideAppInitializer(async () => { await inject(ConfigLoader).fetch(); })
Environment Initializerの利用検討
アプリ起動前初期化が必要な場合は:provideEnvironmentInitializer()
とprovideAppInitializer
を使い分け
移行後の検証手順
ng serve
実行後、コンソールエラーをチェック- 初期化処理が正しく実行されているかログで確認
- 依存サービスがundefinedになっていないかテスト
Angular 19では初期化メカニズムがシンプルかつ型安全になりました。適切な移行によりアプリケーション起動プロセスの信頼性が向上します。