メインコンテンツにスキップ

リアクターフィーチャーフラグ: 完全な実装ガイド

Reactの機能フラグを実装する方法を学びましょう。完全なガイドで、構造パターン、ロールアウト戦略、CI/CD、モダンアプリのためのベストプラクティスをカバーしています。

React機能フラグ:完全な実装ガイド

あなたは機能を完成させました。プルリクエストはきれいです。QAは良さそうだと言っています。でもあなたはまだ全員に同時に配信したくありません。

通常、Reactアプリが単純なデプロイから成長した最初の兆候は、このような気分です。製品が実際のユーザーに公開されると、リリースは技術的なイベントだけではなくなります。リスクの決定になります。新しい検索UIが壊れたり、チェックアウトバリエーションがユーザーを混乱させたり、またはモバイルビルドがcodeを実行した場合、迅速に戻すことができない場合、より多くの if (process.env.NODE_ENV) と期待するだけではありません。

その時 react機能フラグ start to matter. Not as a cute boolean in a component, but as a release control layer that lets you ship code separately from exposing it. In web apps, that means safer rollouts. In bundled apps like Capacitor or Electron, it matters even more because rollback speed is limited by store review, install lag, and slower release cycles.

目次

モダンなReactアプリのための機能フラグの重要性

金曜日の午後リリース。新しい請求サマリUIはすでにデプロイされており、サポートはリリースチェックリストを開いており、1つのエンタープライズクライアントはまだ月曜まで古いフローを必要としています。ウェブアプリケーションではすでに緊張感があります。デスクトップインストーラーやモバイルストアから配信されるバンドルされたReactアプリケーションでは、ロールバックが分数ではなく時間か日数かかるため、状況がさらに悪くなります。

Feature flags give React teams control over that moment. They let you ship the code, keep it dormant, and decide later which users should see it. That changes release work from an all-or-nothing event into a controlled operation.

機能フラグの重要性を強調するグラフィックの説明。

デプロイとリリースは異なる仕事です。

デプロイは「codeが生産環境にありますか?」と答える。リリースは「この動作を現在実行できるユーザーは誰ですか?」と答える。

実際のトラフィック、複数の環境、収益、権限、ナビゲーションに関連する機能を持つReactアプリケーションが存在する場合、その区別は重要です。チームは早期にマージし、内部コホートで生産環境でテストし、機能がすべてのユーザーに適合するまでアクセスを拡大することができます。スローアップデートプラットフォームであるCapacitorアプリケーション、Electronアプリケーション、ストアでレビューされたモバイルビルドなどでは、その制御はさらに価値があります。ユーザーの手元にすでにバイナリが存在している場合、すべてのユーザーに機能が適合するまでに時間がかかる可能性があります。

機能フラグは3つの状況で役立ちます:

  • 制御されたロールアウト: 新しいパスを小さなグループに公開する
  • 実験: バリアントを比較するには別々のデプロイを維持する必要はありません。
  • 高速シャットダウン: 機能をリスクのあるものから無効にするには、ビルドの新しいバージョンを待つ必要はありません。

生産性の高いルールはここでもうまく機能します。生産性の低い問題を修正するコストが高くなければならない場合、その code をフラグの背後で配達します。

UI 条件付きを止めてしまうチームは、新しいフラグの使い方を学ぶことが少ないことが多いです。 flag ? <NewUI /> : <OldUI /> React機能フラグは、ユーザーに表示される部分ですが、実際には面白い部分ではありません。機能フラグのコア価値は、運用上の価値です。リモート設定、決定論的ターゲット設定、機能を即時停止できる機能が、実稼働環境で機能フラグを有効にする上で役立ちます。 remote config plugin for Capacitor apps リリース管理モデルに合致する。

フラグは信頼されていない場合、役に立たなくなる

フロントエンドコードベースが大きくなるにつれて、同じエラーのパターンをよく見ます。チームはフラグを急速に追加し、環境間で名前がずれ、デフォルト値が設定ミスを隠し、誰もが「オン」がグローバルにオン、スタッフ用にオン、またはステージングでオンのみを意味するのかわかりません。その時点で、フラグシステムはリスクを減らすのではなく、リスクを生み出します。

Type safety helps, but it does not solve the whole problem. Teams still need a clear registry, ownership, and a consistent way to evaluate flags across the app. Otherwise, React components end up making local assumptions about rollout state, and those assumptions break during launches or partial rollbacks.

差は簡単にわかります。

利用例 弱いバージョン 強いバージョン
UI スイッチ コンポーネントのローカルブール値 所有権とロールアウトルールを持つリモートフラグ
リリースの安全性 手動のデプロイロールバック リモート設定を通じて即時無効化
実験 アドホックブランチの比較 安定したコホートの割り当てと測定可能な露出

Reactアプリの重要な意識のシフトは単純です。 Reactの機能フラグはリリースプロセスに属しますが、JSXに限りません。 それをそう扱うようにしてください、特に、ビルドを新しく出荷するのが遅いアプリでは、機能フラグは、生産が混乱したときに、爆発半径を減らすために、唯一のツールの1つになります。

Reactアプリの機能フラグのアーキテクチャ

アーキテクチャの決定は最初のフラグよりも重要です。 ランダムなコンポーネントにフラグを直接接続すると、論理の重複、ロードのフリッカー、誰もが信頼できるソースを知らないコードベースが生まれます。

ランタイムプロバイダーを使用せずに散在した条件分岐を使用しない

Reactアプリの信頼できるアプローチは、フラグを ランタイムデータ. Guidance for React flagging recommends three things: evaluate flags on the server or in a local SDK cache, persist cohort assignment deterministically, and render the final UI state before hydration or use anti-flicker protection so users don’t see the wrong default first (Reactフラグの方法論).

これは、codeの場所を変更します。 フラグのロードをアプリのルート近くに置き、消費を簡単にします。 リーフコンポーネント内でフラグを取得するのを避けます。

実用的な形は次のようになります:

  1. メインツリーがレンダリングされる前に、フラグをロードまたはハイドレートします。
  2. プロバイダーを通じて公開します。
  3. hookまたはwrapperパターンを通して読み取ってください。
  4. プレゼンテーショナルコンポーネントから評価ロジックを外すようにしてください。

アプリ全体の設定やフラグのためのリモート設定層が必要な場合、hybrid React アプリで自然に合致するツールとして Capacitor リモート設定プラグイン を使用することができます。

パターン1: React Contextとカスタムフック

一般的に推奨するデフォルトパターンです。明確でテストしやすく、後で提供元を切り替える場合に簡単に移行できます。

import React, { createContext, useContext, useMemo } from 'react';

type FlagValue = boolean | 'control' | 'variant-a' | 'variant-b';

type Flags = {
  newCheckout: boolean;
  checkoutExperiment: FlagValue;
  deleteTaskEnabled: boolean;
};

const defaultFlags: Flags = {
  newCheckout: false,
  checkoutExperiment: 'control',
  deleteTaskEnabled: false,
};

const FeatureFlagContext = createContext<Flags>(defaultFlags);

export function FeatureFlagProvider({
  flags,
  children,
}: {
  flags: Flags;
  children: React.ReactNode;
}) {
  const value = useMemo(() => flags, [flags]);
  return (
    <FeatureFlagContext.Provider value={value}>
      {children}
    </FeatureFlagContext.Provider>
  );
}

export function useFeatureFlag<K extends keyof Flags>(key: K): Flags[K] {
  return useContext(FeatureFlagContext)[key];
}

使用方法は面白くありませんが、これが望ましい結果です。

function DeleteTaskButton() {
  const enabled = useFeatureFlag('deleteTaskEnabled');

  if (!enabled) return null;
  return <button>Delete task</button>;
}

このパターンは、コンポーネントが最終的な答えを求めるだけなので、答えがどのように計算されたかは気にしません。

パターン2: 高階関数

高階関数 A React機能フラグパターンを比較する

import React from 'react';
import { useFeatureFlag } from './FeatureFlagProvider';

export function withFeatureFlag<P>(
  flagKey: 'newCheckout' | 'deleteTaskEnabled',
  Fallback?: React.ComponentType<P>
) {
  return function wrap(Component: React.ComponentType<P>) {
    return function FeatureFlaggedComponent(props: P) {
      const enabled = useFeatureFlag(flagKey);

      if (!enabled) {
        return Fallback ? <Fallback {...props} /> : null;
      }

      return <Component {...props} />;
    };
  };
}

使用方法:

const CheckoutPage = () => <div>New checkout</div>;
const LegacyCheckoutPage = () => <div>Legacy checkout</div>;

export default withFeatureFlag('newCheckout', LegacyCheckoutPage)(CheckoutPage);

欠点は、間接性です。モダンなReactでは、フックはより簡単に追跡できますが、HOCは開発ツールでコンポーネントツリーを汚染する可能性があります。ただし、ルートレベルでのゲーティングでは、汚染されません。

コンポーネントはロールアウトポリシーを決定するのではなく、フラグの結果を受け取り、バケット化、ユーザー対象化、キャッシュ更新のルールを実装するのではなく、コンポーネントを消費するようにしてください。

React機能フラグパターンを比較する

基準 コンテキスト+フック Higher-Order Component (HOC)
ベストケース コンポーネントレベルでの決定とバリアント フルページ、ルート、またはレガシーコンポーネントをラップする
柔軟性 High Medium
開発者体験 現代の機能コンポーネントで強い フックが不便な場合に便利
バンドル明確性 明確なインポートと直接的な読み取り 木構造におけるより多くの抽象化
テスト プロバイダーを介して簡単にモックできる ラップされた統合ケースが簡単
長期的なメンテナンス性 通常は良好 適切に使用する場合

初めて React の機能フラグを実装する場合、まずは コンテキスト + ハック. HOC を追加するのは、特定のニーズがある場合に限り

ロールアウトとロールバック戦略の実装

機能がリリース後に不正動作を起こした場合、ロールアウト計画は最も重要です。UI は新しいボタンや画面を表示するだけですが、最初に誰がそれを見るか、露出の速度、そして待ってリデプロイするのではなく、すぐにシャットダウンできるかということが重要です。特に、モバイルまたはデスクトップのパッケージ内でリリースされる React アプリの場合、ロールバックはリモート設定に依存することが多く、レビューまたはデスクトップ配布には時間がかかるためです。

ソフトウェア機能フラグのロールアウトとロールバック戦略のファンルーム

パーセンテージロールアウトには固定割り当てが必要

パーセンテージロールアウトは、割り当てが安定している場合にのみ機能します。同じユーザーが 1 回の訪問で新しいチェックアウトを、次の訪問で古いチェックアウトを表示した場合、サポートは問題を再現できず、分析はノイズが増し、ユーザーは信頼を失います。

解決策は簡単です。ユーザーを安定した識別子とフラグキーを組み合わせた決定論的ハッシュでバケット化するだけです。ユーザー ID は通常の入力になります。匿名セッションでは、インストール ID またはデバイス ID を使用できます。 Math.random() ブラウザ内では、ユーザーを予測できないように再割り当てするため、間違ったツールです

実際的なロールアウトパスは次のようになります。

  • 内部ユーザーとQAから始めましょう。
  • 小規模コホートにリリースする。
  • エラー率、変換の影響、サポートチケットを確認した後、段階的に拡大する。
  • フラグの有効期間中、割り当てを固定する。

Stickyコホートは実験のみに使われるものではありません。 そのコホートは、エンジニアが即座に回答できる基本的な質問に役立ちます: どのユーザーが影響を受けたか?

実験を実行する場合は、実験を実行する前にサイズを設定してください。 Optimizely から提供されるサンプルサイズ計算ツールは、トラフィックの量、基準変換率、最小検出可能効果が必要なユーザー数の変異数をどのように変化させるかを示しています ("サンプルサイズ計算ツール機能フラグをチェックしない場合、チームはノイズを信号と誤認し、機能を早期に推進することがよくあります。

外部ブラウザのステージドアップデートのための便利なリファレンスです。 phased rollouts for Capacitor live updatesReact アプリがパッケージ化されたシェル内で実行される場合、同様のリリース規則が適用されます。バイナリのロールバックは遅くなります。

ターゲットとリングベースのリリースは爆発半径を減らします。

特定の機能はランダムなパーセンテージで始めるべきではありません。請求フロー、承認プロンプト、データ移行、ユーザーをロックアウトする可能性のあるものは、ターゲットリリースで始めるべきです。

ターゲットは、最初のアウディエンスが既知の特性で定義されている場合にうまく機能します:

  • 内部スタッフのためのドッグフード
  • ベータテスターが粗いエッジに同意したもの
  • 特定のアカウント階層
  • 法律または言語要件が異なる地域
  • 機能を安全にサポートするデバイスまたはアプリバージョン

リングベースのリリースは、ターゲットをより実行可能にします。リング0は従業員です。リング1は信頼できる外部テスターです。後続のリングは信頼性が向上するにつれて露出を拡大します。この構造は、リスクが明らかに不均等である場合に、チームがユーザーを一つのプールとして扱うことを避けるのに役立ちます。

ここに、このリリースモデルと組み合わせるのに適した埋め込みウォークスルーがあります。

キルSwitchは、機能を稼ぐ旗です。

リスクのある機能には、迅速なオフパスが必要です。実際には、通常はトップレベルのオペレーショナルフラグで機能フロー全体を無効にする必要があります。プレゼンテーショナルフラグでは、バックグラウンドの要求、効果、ナビゲーションパスがまだ実行されている場合に、しかるべきエントリポイントだけを非表示にするだけではありません。

リリース前にkill switchを設計する:

  • アプリ起動の早い段階で評価する。
  • 最後の安全な値をキャッシュする。
  • フラグサービスが利用できない場合に安全なデフォルト値を選択する。
  • 機能を無効にすることで、サイドエフェクトが停止することを確認する。
  • インシデントの際にフラグを切り替えることができるのは誰かをドキュメントする。

ウェブアプリのみの場合、リリースリスクが減る。モバイルやデスクトップのReactアプリの場合、重大なインシデントとユーザーが修正されたビルドを待つことの差が生まれる。すでにcodeがバンドルに含まれている場合、リモートフラグはロールバック戦略の一部になるのではなく、リリース戦略の一部になる。

機能フラグのテスト、観察性、フラグの負債の管理

機能フラグの簡単な部分は、1つを追加すること。高価な部分は、多くのフラグが存在し、誰もそのうちどれがまだ重要かを覚えていないときに始まる。

モダンなサーバールームの写真。サーバーラックと点滅する光と整理されたネットワークケーブルが並んでいる。

各フラグは、信頼できる状態の数を増やす。

マーティン・フラワーの警告はまだ有効である:機能フラグが存在する場合、チームは両方の検証を実行する必要がある。 On と Off 状態、特に複数のフラグがある場合、可能な状態の組み合わせは組み合わせ爆発的に増加し、バグのリスクが高まる (マーティン・ファウラーによる機能フラグ).

それが、React アプリケーションに直接影響する:

  • 条件付きレンダリングのパスが急速に広がる: 1 つのページが複数の branch を持つことができる:
  • hydration の不一致が起こりやすくなる: クライアントとサーバーが評価のタイミングが異なる場合に異議を唱えることができる:
  • スナップショット テストが単独で役に立たなくなる: ハッピーパス レンダリングだけでは、フラグの反対の状態がテストされていない場合に何も教えてくれない。

実用的なテストスタックは以下のようになります。

  1. 単位テストを実行して評価ロジックを確認する。
  2. コンポーネントテストキーのフラグ付けされたブランチ。
  3. エンドツーエンドのカバレッジを、リスクのあるパスのみに追加してください。
  4. デフォルトのフォールバックを明示的に検証する。

すべての組み合わせを目指すのではなく、ユーザーに損害を与える可能性のある状態やレイアウトを崩す可能性のある状態をテストすること。

フラグ負債は実際に存在し、静かに高額になる

古いフラグはcodeの状態が悪くなり、条件分岐、コメント、ダッシュボード、実行書に残ります。 その後、誰かが「一時的な」ブランチを数ヶ月後に編集することになりますが、誰も削除していませんでした。

実際に機能するクリーンアップルールは簡単です。

Issue 何をしますか。
No owner __CAPGO_KEEP_0__
フラグが作成されたときにチームまたは人を割り当てる 終了状態がない
フラグが削除、保持、または設定に変換されるかどうかを決定する フラグがあまりにも多くの制御を握っている
フラグに隠されたコアロジック ビジネスロジックをレンダリング条件から外す

クリーンアップルール: フラグには1日以内に所有者、目的、削除計画が必要である

チームが「信頼」問題に陥るのはここで起きる。フラグ名は存在するが、フォールバックが間違っている。ダッシュボードエントリが変更されたが、アプリタイプが変わっていない。codeパスは死んでいるが、まだアクセス可能な

観測性はフラグが役に立ったか、ただ存在したかを教えてくれる

ロールアウトはフラグが完全に露出した時点で終了ではない。チームが何が起こったかを知るまで終了ではない

質問を追跡するには少なくとも以下の質問を考慮する必要があります:

  • 露出: どのユーザーがどのバリアントを視認したか?
  • エラー: フラグされたパスがクライアントサイドのエラーを引き起こしたか?
  • 採用: ユーザーが公開された機能を使用したか?
  • ロールバック信号: どの閾値が機能をオフにするのに十分か?

フラグプラットフォームが上記の質問に答えられない場合、リリースレビュー中にまだ推測することになります。

フラグのセキュリティとCI/CDの自動化

A bad deploy is obvious. A bad flag change is quieter, and in some cases more dangerous, because it changes production behavior without going through the same review path as code.

A CI/CDプロセスとツールを使用した機能フラグのセキュリティとワークフローの自動化を示す図です。

プロダクションの変更と同様にフラグの変更を扱う

機能フラグはリリースの制御です。プロダクションでフラグを切り替えることができるチームは、ユーザーに何が表示されるか、どのcodeパスが実行されるか、そして時々どの統合が発火するかを決定できます。これには、デプロイアクセスの同様の規律が必要です。

最小限の制御は以下のとおりです。

  • ロールベースのアクセス制御: プロダクションフラグの変更を制限し、読み取りアクセスと編集アクセスを分離する
  • 監査ログ: フラグの変更を誰がいつ行ったか、どの環境を変更したかを明確に記録する
  • 環境隔離: ステージング、プレビュー、プロダクションフラグを区別することで、テスト変更がライブトラフィックに影響しないようにする
  • サーバー側のチェックによる敏感な決定: クライアントフラグはUIを非表示にすることができますが、請求アクセス、特権、認証を決定するには使用してはなりません。

A flag ダッシュボードを共有スプレッドシートのように扱うのはよくない。顧客に機能を有効にする製品、機能を無効にするサポート、機能が変更されていないと仮定するエンジニアリング。この設定は、インシデントを説明する必要があるまで機能する。

バンドル アプリではリスクが高くなる。Web アプリでは、code の修正が迅速に配信できる。Capacitor またはデスクトップ アプリでは、既に code の破損がデバイスに待機している可能性がある。code で React モバイル アプリを構築するチームは、 Capacitor で React モバイル アプリを構築するチームは、 ロールバックは、機能を無効にする代わりにバイナリを置き換えることができないため、承認ルールについては厳格にしなければならない。

フラグ オペレーションをパイプライン内に含める。

フラグが外部プロセスから独立している場合、信頼性が低くなる。安全なパターンは、機能を配信するワークフローと同様に管理することである。

通常、次のことが必要になる。

  • 機能 code の PR でフラグを作成または更新する。
  • CI でリモート レジストリとタイプ付きフラグ定義を検証する。
  • 環境ごとにデフォルト値を意図的に設定する。
  • 必要なフラグが欠落しているか、不正に設定されている場合にリリースをブロックする。
  • 期限切れまたはロールアウト終了状態のフラグにスケジュールされたクリーンアップタスクを設定する。

I prefer a simple rule: if a production incident could be caused by a flag, CI should be able to catch the setup before release. That includes missing defaults, renamed keys, stale environment mappings, and flags that exist in code but not in the control plane.

パイプライン構造のスターティングポイントが必要な場合は、 Git Action CI/CD ワークフロー ビルドチェック、デプロイゲート、フラグ検証の拡張に使用できる自動化ステップの例として

秘密とSDKの選択肢を面白くしないでください。

フラグのセキュリティを過度に複雑にするフロントエンドチームは、明らかな部分を無視します。ブラウザで設計された一般的なクライアントサイドSDKキーは、通常問題ありません。管理トークン、書き込みクレデンシャル、環境管理キーはCIまたはバックエンドサービスのみに属します。

実用的には、単純です。プレゼンテーション変更や低リスクの実験にはクライアントサイド評価を使用し、価格、許可、敏感なフローへのキルSwitch、ローカルJavaScriptに信頼できないものはサーバーサイド評価を使用します。

この境界は、スローピースの環境ではより重要です。Webチームは迅速なデプロイで回復できます。モバイルとデスクトップチームは、フラグシステムが回復メカニズムになる必要があります。間違った人が生産フラグを編集できる場合、またはCIがフラグ契約を検証しない場合、ロールバックは迅速に混乱します。

Web Feature Flags for Capacitorとモバイルアプリケーション

Reactアプリが即時再デプロイできるものと想定している多くの記事は、Reactのcodeがサーバー上に存在する場合に限ります。 Capacitor, Electron、または別のバンドル実行環境。

バンドルアプリケーションはリリースの計算式を変える

ハイブリッドアプリでは、ユーザーがすぐに更新しないようにするJavaScript、CSS、アセット、設定を含むバンドルを配信することがよくあります。機能はすでにデバイス上にありますが、誰もがそれを使用することを望まない場合、変更点は大きいです。

最近のハイブリッドリリース戦略に関する議論では、すでに存在するReactフラグのコンテンツがCapacitorまたはElectronアプリのリリースリスクモデルに対処していないことが指摘されました。 そのチームにとって、主なニーズは、フラグ、ターゲットチャンネル、ロールバック保護を組み合わせたリリースオーケストレーションレイヤーです。 特に、ストアのレビュー遅延を回避することが重要な場合、単純なオン/オフスイッチではありません。ハイブリッドアプリのリリースリスクの議論).

これはまた、チャンネルベースの配信の重要性を示しています。 ハイブリッドアプリを構築している場合、そしてアプリシェルとWeb__CAPGO_KEEP_0__のリリースモデルが一緒に機能するようにしたい場合は、 __CAPGO_KEEP_0__.

Electron

code creating React mobile apps with Capacitor は実践的な出発点です。

フラグは、更新の配信と組み合わせて最も効果的です。

For mobile and desktop teams, flags alone won’t solve every release problem. They can hide or enable code paths, but they can’t replace shipping fixed assets or logic when the bug is already in the bundle.

したがって、より強力なモデルは次のとおりです。

  • プラットフォームが許可する場合、codeの更新をフルストアサイクル外で配信し
  • チャネルまたは対象者に焦点を当てて
  • フラグを使用してアクティベーション、ロールバック、ステージドエクスポージャーを制御します。

ライブアップデートとフラグを組み合わせると、ハイブリッドチームはウェブスタイルのリリース制御に近いものを手に入れます。ただし、 disciplineを失うことなく、より多くのレバーを使用できるようになります。


チームがCapacitorまたはElectronアプリを配信し、リリース制御層が必要な場合 Capgo は、ターゲットされたチャネルに署名されたウェブバンドルを配信し、ロールバック保護と観察性をサポートし、機能フラグがライブアップデートと組み合わせて機能する必要があるハイブリッドアプリのワークフローに適合するため、__CAPGO_KEEP_0__を検討するオプションの1つです。

React機能フラグ: 完全実装ガイドから続きます。

あなたが使用している React機能フラグ: 完全実装ガイド チャネルルーティングとステージドロールアウトを計画するには、 チャネル チャネル チャネル チャネル チャネル チャネル チャネル チャネル バージョン対象ソリューション バージョン対象ソリューション用の製品ワークフロー

Capacitorアプリ用の即時更新

Capgoでウェブ層のバグが実行中の場合、Capgoを通して修正を配信するのではなく、数日間待ってアプリストアの承認を待つ必要がなくなる。ユーザーはバックグラウンドで更新を受け取り、ネイティブの変更は通常のレビューのパスを通る。

最新のブログ

Capgoは、プロフェッショナルなモバイルアプリを作成するために必要な最高の洞察を提供します。