🚩

[Angular]canMatchを使ってFeature Flagを実現する

2023/12/05に公開

はじめに

最近、Feature Flagについての記事や事例を目にすることが増えてきましたね。
Feature Flagの様々なメリットについての説明は素晴らしい記事が沢山ありますので、ここでは割愛します。
今回はAngularでcanMatchを使って、同じパスを持つ2つのコンポーネントをDev環境・Prod環境それぞれで出し分けることによって、Feature Flagを実現します。

成果物

完成したコードは以下のレポジトリに配置しています。

https://github.com/rysiva/in-progress-angular

手順1: Environment型を定義し、各環境の設定値を記述

今回はサンプルとしてLocalProdの2つの環境を用意しました。

https://github.com/rysiva/in-progress-angular/blob/main/src/app/environment.model.ts
https://github.com/rysiva/in-progress-angular/blob/main/src/app/environment.ts
https://github.com/rysiva/in-progress-angular/blob/main/src/app/environment.prod.ts

手順2: InjectionTokenの作成

トークンに注入する値の型を定義します。

https://github.com/rysiva/in-progress-angular/blob/main/src/app/environment.config.ts#L4-L6

手順3: appConfigの定義・bootstrap

ENVIRONMENT_CONFIGトークンに environment オブジェクトの値を使用します。

https://github.com/rysiva/in-progress-angular/blob/main/src/app/app.config.ts#L7-L15
bootstrapApplicationの引数として、AppComponentとappConfigを渡します。
https://github.com/rysiva/in-progress-angular/blob/main/src/main.ts#L5-L7
AppComponentはrouter-outletを置いているだけです。
https://github.com/rysiva/in-progress-angular/blob/main/src/app/app.component.ts#L9

手順4: guardの定義

inProgressGuardではシンプルに、environmentのinProgressの設定値(boolean)を返します。

https://github.com/rysiva/in-progress-angular/blob/main/src/app/in-progress.guard.ts

手順5: routesの定義

canMatchを使うことで、同じpathを持つ複数のルートを条件分岐できます。
inProgressGuardがfalseを返した場合、DevelopInProgressComponentへのルートはスキップされ、次のルートが処理されます。

https://github.com/rysiva/in-progress-angular/blob/main/src/app/app.routes.ts#L4-L14

手順6: ビルド時に参照するenvironmentファイルを環境ごとに変更する

productionビルドの際にenvironment.prod.tsを参照するよう設定します。
※ちなみに本プロジェクトではNxを使用しています。

https://github.com/rysiva/in-progress-angular/blob/main/project.json#L39-L40

動作確認してみよう

developmentビルドした結果

$ nx run in-progress-angular:build:development

$ http-server dist/in-progress-angular/browser

Image from Gyazo


productionビルドした結果

$ nx run in-progress-angular:build:production

$ http-server dist/in-progress-angular/browser

Image from Gyazo

同じpath''に遷移していますが、環境ごとに違うComponentを表示させることに成功しました。

おわりに

今回はルートレベルで制御しましたが、作成したconfigはComponentの中でinjectして使用することもできます。
Angularの新しい制御フローを使って、Componentの中で条件分岐させてみても面白いかもしれませんね。

5日目の記事はrch850さんによるAngular 17 の View Transitions API 対応で遊んでみたです!

参考文献

🚀 Introducing the CanMatch Router Guard In Angular


編集後記

バーベルのオーバーヘッドプレスをしていたら、首を痛めました。
皆様もお気を付けください。

Discussion