リスクなしで
ソフトウェアを
より速く革新
Innovate Your Software Faster without Risk
BlazorでのFeature Flags の実装方法
この記事は LifeCycle によって書かれました。ここで英語で書かれたオリジナルの記事を確認できます

Twitter でフォローして、トピックや改善に関する提案をお待ちしています。
はじめに
多くのサードパーティの Feature Flags サービスが利用可能であり、あるいは内部チームが独自のFeature Flags サービスを開発することもあります。 標準化を好む方には、OpenFeatureのガイドラインに従うという選択肢もあります。 しかし、これらの解決策のいずれも、特に多くの人にとっては新しい領域であるBlazorプロジェクトには完全にフィットしないかもしれません。 さらに、Microsoft.FeatureManagementライブラリですら、Blazorに対して十分なサポートを提供していません。
このブログ記事では、サードパーティのFeature Flags ツールを使用して、BlazorでのFeature Flags の実装方法に関する私のInsightsを共有します。
さまざまな手法を試してきましたが、この投稿では、Blazorでの Feature Flags の実装手法として、次のアプローチを紹介します:
- 伝統的な方法:if/else文を使用してフィーチャーを制御する方法。 この方法はバックエンドとフロントエンドの両方に適用可能です。
- タグヘルパーの代わりにコンポーネントを使用:このアプローチはフロントエンドでFeature Flags コードをラップし、Server-Side Rendering(SSR)およびWebAssemblyの両方に効果的です。
- カスタムフィーチャーゲート属性:Feature Flags がリクエストのために有効になっていない場合、404エラーが返されます。
- ルートフィルタリング:ページアクセスを制御します。 Feature Flags がリクエストのために有効になっていない場合、404ページにリダイレクトされます。"
Blazorの開発者からフィードバックを得て、このブログ記事を更新したいと考えています。
ここをクリックして、この記事で使用されているコードソースをダウンロードしてください.
Asp.Net Core 8 Blazor Web APPを作成する
簡単なBlazor Web Appを使用して手法を紹介します。 Blazor Web Appを選択し、次へをクリックして、新しいASP.NET Core 8 Blazor Web Appを作成できます。

プロジェクトに名前を付けて、次へをクリックします。 次に、次のようにプロジェクトを構成し、作成をクリックします
- .NET 8
- HTTPSの構成
- インタラクティブなレンダリングモード:自動(サーバーおよびWebAssembly)
- ページ/コンポーネントの間での相互作用の場所

Blazor Web Appプロジェクトができました。プロジェクトを実行してデフォルトページを表示します。 このプロジェクトでFeature Flags の実装を開始します。
サードパーティのFeature Flags ツールを選択する
LaunchDarkly、Unleash、Microsoft.FeatureManagementなど、さまざまなサードパーティの Feature Flags ツールが利用可能です。 ただし、このブログ記事では、何らかの理由から、FeatBitを使用します:
- FeatBitは、幅広い無料プランを提供するオープンソースプロジェクトです。 .NETを主要なフレームワークとして利用する企業で広く使用されています。
- プロジェクトのバックエンドサービスは.NETで構築されており、堅牢なリアルタイム更新される.NET SDKが含まれています。
- FeatBitは、Feature Flags のライブラリにとどまらず包括的なFeature Flags 管理サービスを提供しています。
Feature Flags SDKのインストールと初期化
Blazor Web Appのサーバープロジェクトで、NuGet Package Managerを使用してFeatBit .NET SDKをインストールします。

SDKのチュートリアルに従って、Program.cs
ファイルにFeatBitサービスを追加してSDKを初期化します。
// FeatBitサービスを追加
builder.Services.AddFeatBit(options =>
{
options.EnvSecret = "<環境シークレットを置き換える>";
options.StreamingUri = new Uri("ws://localhost:5100");
options.EventUri = new Uri("http://localhost:5100");
options.StartWaitTime = TimeSpan.FromSeconds(3);
});
このように、プロジェクトのProgram.cs
ファイルは次のようになります:

初期化されたSDKを使用して、Blazor Web AppでFeature Flags を実装できるようになりました。
方法1:if/elseを使用してフィーチャーを制御する
この方法は、バックエンドとフロントエンドの両方に適用でき、わかりやすいアプローチを提供します。 両方の領域でフィーチャー(またはコードブロック)を制御する柔軟性を提供します。
例えば、ホームページに新しいウェルカムセンテンスを追加し、Feature Flags を使用して制御したい場合、次の手順を実行します。
Home.razor
ファイルに次のコードを追加してサービスを注入します:
@inject IFbClient FeatureFlags
- レイザーコードブロック内で、元の「Hello World」コードの後に次のコードを追加します:
@if (FeatureFlags.FeatureReleased("weather-page"))
{
<h5>
ウェブサイトへようこそ!私たちはあなたをここで歓迎し、一緒に歩むことを心待ちにしています。
</h5>
}
上記のコードは、FeatureFlags
が前の手順で注入されたサービスであることを示しています。 FeatureReleased
は、そのパラメータとしてFeature Flags のキーを持ち、Feature Flags が有効になっている場合、ウェルカムセンテンスのコードブロックがレンダリングされます。
プロジェクトのHome.razor
ファイルでは次のようになります:

注: FeatureReleased
メソッドはFeatBitによって提供されるものではなく、私が作成した拡張機能で、FeatBitのBoolVariationメソッドをカプセル化しています。 拡張機能のコードを見ると、かなり簡単であることがわかります:

FeatBit SDKは、ユーザーを識別するためのユーザーパラメータが必要です。 この例では、デモを簡略化するために、ユーザーIDを持つランダムIDのユーザーオブジェクトを渡しました。 ただし、実際のアプリケーションでは、一意のIDを持つユーザーオブジェクトを渡す必要があります:
- ユーザーがログインしている場合は、UserId、Name、およびフィーチャーリリースに役立つその他の情報を渡します。
- ユーザーがログインしていない場合は、ランダムなIDまたはCookie IDを渡します。同じエンドユーザーは常に同じIDを取得するようにしてください。
詳細については、SDKのチュートリアルを参照してください。
コードにFeature Flags を実装すると、プロジェクトを起動するとFeature Flags が常に無効になっていることに気付くかもしれません。これはBoolVariation
メソッドがデフォルトでfalse
を返すためです。Feature Flags を有効にするには、FeatBitのダッシュボードに移動し、「welcome-sentence」という名前のFeature Flags を作成して有効にします。
FeatBitダッシュボードでFeature Flags を作成する
- 「Feature Flags 」ページに移動し、右上隅の緑色の**+ 追加**ボタンをクリックします。
- ポップアップドロワーで、Feature Flags に「welcome-sentence」という名前を付けます。

- タイプとして
boolean
を選択します。 - 他の項目はデフォルト値のままにして、保存をクリックします。

ユーザーに「Welcome Sentence」を表示するには、単にプロジェクトを再起動し、ダッシュボードでFeature Flags を有効にするか、徐々にフィーチャーを展開することができます。以下にその方法を示します。

左パネルでFeature Flags をアクティブにします。右パネルで、デフォルトルールを構成して、エンドユーザー(またはリクエスト)の100%に対してtrue
の値を返すようにします。
方法2:コンポーネントを使用して機能を制御する
BlazorではTagHelperの代わりにコンポーネントを使う方法があります。このアプローチは、フロントエンドのFeature Flags コードブロックをラップし、サーバーサイドレンダリング(SSR)およびWebAssemblyの両方に有効です。このアプローチは以前のものと似ていますが、if/elseステートメントの代わりにFeature Flags コードブロックをラップするためにコンポーネントを使用します。

FeatureFlag
コンポーネントは、Feature Flags のキーをパラメーターとして受け取り、Feature Flags が有効な場合にのみ子コンテンツをレンダリングするシンプルなコンポーネントです。以下は、このコンポーネントの設計と実装方法です。
FeatureFlag
コンポーネントは、Feature Flags のキーをパラメーターとして受け取り、Feature Flags が有効な場合にのみ子コンテンツをレンダリングします。これは、共有コンポーネントとFeatureReleased
メソッドを使用してFeature Flags の状態をチェックすることで実現されます。フラグが有効な場合、子コンテンツがレンダリングされます。

このコンポーネントは、サーバーサイドレンダリング(SSR)プロジェクトとWebAssemblyプロジェクトの両方で実装しました。現在、この機能をより効率的に実現する方法を探っていますが、まだ代替案を見つけていません。もしご提案やより良いアプローチがあれば、お知らせください。

方法3:Controllerアクションのためのカスタムフィーチャーゲート属性
前の2つの方法とは異なり、この方法はバックエンドに特化したものです。これはコントローラーアクションへのアクセスを制御します。ユーザーまたはリクエストにFeature Flags が有効になっていない場合、メソッドは404エラーを返すことになります。
このプロジェクトでは、"WeatherForecastController"というAPIコントローラーを作成しました。このコントローラーには特別な天気予報のアルゴリズム用のAPIが含まれています。たとえば、次の7日間の空気SO2品質予測を取得するには、api/WeatherForecast/AirQualitySO2Algo
APIを呼び出すことができます。ただし、このAPIへのアクセスは制限されており、承認を受けたユーザーまたはリクエストのみが利用できます。
以下のコードは、このAPIへのアクセスを制御するためにカスタムの'FeatureGate'属性を使用する方法を示しています。

FeatureGate
属性をAPIapi/WeatherForecast/AirQualitySO2Algo
アクションに追加します。- Feature Flags のキーを最初の属性パラメーターとして設定します。
- デフォルト値として
regression
を設定します。これはデフォルトで(たとえば、対応するFeature Flags が作成されていない場合)Feature Flags がregression
の値を返すことを意味します。 - パスの値の1つとして
metnet
を設定します。これは、Feature Flags がmetnet
を返さない場合、APIは404エラーを返すことを意味します。
このカスタム属性を実装してAPIアクセスを制御することは簡単で効率的です。これにより、Feature Flags で制御されているAPIを簡単に特定することができます。また、属性でFeature Flags のキーを変更することも簡単にできます。
このカスタム属性の実装について詳しく見ていきましょう。 OnActionExecutionAsync
メソッドでは、FeatBit SDKのStringVariation
メソッドを使用してFeature Flags のステータスをチェックしています。Feature Flags が'PassedValues'文字列リストで定義された値を返さない場合、404エラーが返されます。

Feature Flags のカスタム属性のログックを開発することができます。ここで提供されている例は基本的なものですが、柔軟性を高めるために属性に他のパラメーターを追加したり、BoolVariation
、DoubleVariation
、JsonVairation
などの他の変化メソッドを使用したりすることができます。
方法4:ルートのフィルタリング
個々のページにFeature Flags コードブロックを埋め込む必要がなくなるよう、ページへのアクセスを中央集権化する方法を検討しています。
Blazorでは、"Router"コンポーネントがOnNavigateAsync
機能をサポートしています。OnNavigateAsync
ハンドラは、ユーザーが次のような状況に直面したときに呼び出されます。
- ブラウザーで直接そのルートに初めてアクセスしたとき。
- リンクやNavigationManager.NavigateToの呼び出しを使用して新しいルートに移動したとき。
したがって、Routes.razor
ファイルのOnNavigateAsync
メソッドでルート制御を中央に配置しようとしました。

FeatureFlags.PageAllowAccess
メソッドの詳細を見てみると、route-navigation
という単一のFeature Flags を使用してすべてのルートを制御しています。パスはFbUserのカスタム属性として渡され、シンプルで柔軟な管理が可能です。これにより、将来新しいルートを追加する場合でも、新しいFeature Flags を作成する必要がなく、既存のルートリリース戦略のコードを変更する必要がなくなります。

リリース戦略はFeatBitFeature Flags インターフェイスで構成する必要があります。以下の図は、特定の条件に一致するユーザーだけが天気ページにアクセスできることを示しています。

さらに多くのページにアクセスを制御するには、新しいカスタムターゲティングルールを追加するだけです。
機能を柔軟かつ徐々にリリースする
新しいページを追加し、そのリリースを制御することは、Feature Flags 管理の一般的なシナリオです。たとえば、最初にページを10%のユーザーにリリースし、その割合を徐々に100%に増やしたい場合があります。FeatBitはこれを実珅するための簡単な方法を提供しています。
通常、各Feature Flags の呼び出しでユーザー(またはその他の文脈)を渡す必要があります。これにより、同じFeature Flags に対して常に同じ結果を受け取ることができます。この一貫性は、プロダクションでのテスト、ABテスト、プログレッシブリリースなどの実践に重要です。
このプロジェクトでの実装方法の例を以下に示します。FeatureReleased
メソッドにユーザー名を渡してユーザーを識別しました。

FeatBit のFeature Flags インターフェースでは、このユーザーを個々のターゲットリストに含めることができます。以下のイメージでは、真の個々のターゲットリストに属するユーザーのみがwelcom-sentece
フィーチャーにアクセスできることを示しています。

この方法は、効果的な feature management に不可欠な、柔軟でコントロールされたリリース戦略を可能にします。
結論
ほとんどの場合、if/else文を使用してすべてを制御できます。ただし、機能フラグを標準化された方法で管理することを目指している場合、このブログ投稿で紹介した方法を使用できます。また、一貫して簡単に参照可能な方法で機能フラグを使用するために、独自の方法を考案することをお勧めします。このアプローチにより、古い機能フラグの削除が容易になります。
このブログ投稿が役立つことを願っています。ご質問や提案がある場合は、お気軽にTwitterでお問い合わせください。