あなたは機能を完了した。プルリクエストはきれいです。QAは良さそうだと言います。でもあなたは全員に一度に配信したくないです。
その気分は、Reactアプリが単純なデプロイに過ぎないものから、実際のユーザーがいる製品に成長した最初の兆候です。リリースは技術的イベントからリスクの決定に変わります。新しい検索UIが壊れたり、チェックアウトのバリアントがユーザーを混乱させたり、またはモバイルビルドがcodeを取り消すことができない場合、より多くのものが必要です。 if (process.env.NODE_ENV) そして、希望だけではありません。
その時、 react feature flags 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アプリ用の機能フラグは何が必要か
- Reactアプリの機能フラグの設計
- ロールアウトとロールバック戦略の実装
- 観察性のテストとフラグの負債管理
- CI/CDを自動化してフラグを保護する
- Capacitorとモバイルアプリ用のWeb機能フラグの超え
モダンな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 /> Capgoのvisible部分はありますが、実際に面白い部分ではありません。Coreの価値は、実行に必要です。Remoteの設定、決定論的ターゲット、機能をすぐにオフにする能力は、flagsが生産環境で役に立つことを意味します。もし、Reactアプリがアプリ全体の実行時設定も必要であれば、 Capacitor アプリ用のリモート設定プラグイン 同期リリース制のモデルに適合します。
信号旗は信頼されていないときは役に立たなくなる
フロントエンドコードベースが大きくなると、同じエラーのパターンが見られることが多い。チームは旗を速く追加し、環境によって旗の名前が異なるようになる。デフォルト値は設定ミスを隠し、誰も旗の値が「オン」は全体的にオン、スタッフ用にオン、またはステージング環境でオンであるかを把握していない。そうすると、旗システムはリスクを減らすのではなく、リスクを生み出すようになる。
Type safetyが役立つが、全ての問題を解決するものではない。チームは、明確なレジストリ、所有権、全アプリで一貫したフラグ評価方法が必要である。そうでないと、Reactコンポーネントはロールアウト状態についてローカルな仮定を立て、リリースや部分ロールバックの際にその仮定が破綻する。
差は一目でわかります。
| 使用例 | バージョンが弱い | バージョン強化 |
|---|---|---|
| UI切替 | コンポーネントのローカルブール値 | 所有権とロールアウトルールを持つリモートフラグ |
| リリースの安全性 | マニュアルデプロイロールバック | リモート設定を通じて即時無効化 |
| 実験 | アドホックブランチの比較 | 安定したコホートの割り当てと測定可能な露出 |
重要な心の変化は単純です。Reactの機能フラグはリリースプロセスに属します。JSXだけではありません。特に、ビルドを出荷するのが遅いアプリでは、リリースプロセスにそう扱うことをお勧めします。そうすることで、生産性が低下したときに、爆発半径を最小限に抑えることができる限られたツールの1つになります。
Reactアプリの機能フラグのアーキテクチャ
アーキテクチャの決定は最初のフラグよりも重要です。ランダムなコンポーネントにフラグを直接接続すると、重複したロジック、ロード中のフリッカー、誰もがどのソースの真実を信頼するかを知ることができないコードベースが生まれます。
Use a runtime provider, not scattered conditionals
Reactアプリの場合、信頼できるアプローチは、フラグを runtime data. 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フラグの方法論).
That changes where your code should live. Put flag loading near the app root. Make consumption simple. Avoid fetching flags inside leaf components.
実用的な形は次のようになります。
- フラグをメインツリーがレンダリングする前にロードまたはハイドレートする。
- フラグをプロバイダーを通じて公開する。
- フラグを1つのフックまたは1つのラッパーモチーフを通じて読み取る。
- プレゼンテーショナルコンポーネントから評価ロジックを外す。
アプリ全体の設定やフラグのためのリモート設定層が必要な場合は、ツールのようなものを使用する。 Capacitor remote config プラグイン hybrid React アプリケーションに自然に合致するパターンです。
React Context とカスタムフックを使用したパターン 1
一般的に推奨するデフォルトパターンです。明確でテストしやすく、後でベンダーを切り替える場合に簡単に移行できます。
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>;
}
このパターンは、コンポーネントが最終的な答えを要求するのみで、答えがどのように計算されたかは気にしないので、うまく機能します。
HOC を使用したパターン 2
HOC は、フック呼び出しを追加することなく、画面、ルート要素、またはレガシークラスコンポーネントをゲートする場合に便利です。 使用方法: HOC は、DevTools でコンポーネントツリーを汚染する可能性があるため、インデレクトの欠点があります。 modern React では、フックはトレースが容易ですが、HOC は DevTools でコンポーネントツリーを汚染する可能性があります。ただし、ルートレベルゲーティングの場合、HOC は汚染されません。
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} />;
};
};
}
A
const CheckoutPage = () => <div>New checkout</div>;
const LegacyCheckoutPage = () => <div>Legacy checkout</div>;
export default withFeatureFlag('newCheckout', LegacyCheckoutPage)(CheckoutPage);
HOC (Higher-Order Component)
コンポーネントがロールアウトポリシーを決定するのを許さない。コンポーネントはフラグの結果を消費するべきであり、バケット化、ユーザー対象化、キャッシュリフレッシュルールを実装するべきではない。
React機能フラグパターン比較
| 基準 | コンテキスト+フック | 高階関数(HOC) |
|---|---|---|
| ベストケース | コンポーネントレベルの決定とバリアント | フルページ、ルート、またはレガシーコンポーネントをwrapする |
| 柔軟性 | 高 | 中 |
| 開発者エクスペリエンス | 現代機能コンポーネントで強い | HOOKが不便な場合に便利 |
| バンドル明確性 | 明確なインポートと直接的な読み取り | 木構造での抽象化 |
| テスト | プロバイダーを通じて簡単にモックできる | Wrapped Integrationケースのために簡単 |
| 長期的なメンテナンス性 | 通常は良好 | sparingly使用する場合に良好 |
Capgoを使用してReactの機能フラグを実装する場合、最初はCapgoを使用して始めてください。 Context + Hook特定な要件がある場合にのみ、ラッパー スタイルのゲーティング用の HOC を追加してください。
ロールアウトとロールバック戦略の実装
リリース後の機能の不調の場合、UI は新しいボタンまたは画面を表示するだけかもしれませんが、決定するべき最も重要なタスクは、最初に誰がそれを見るか、露出の増加速度、そして再デプロイを待たずにシャットダウンすることができるかということです。 これは、モバイルまたはデスクトップのバンドル内にReactアプリを配布する場合に、特に重要です。 その場合、ロールバックはリモート設定に依存する可能性があり、App Storeのレビューまたはデスクトップの配布には時間がかかります。

パーセンテージロールアウトには、固定 assignment が必要です。
パーセンテージロールアウトは、assignment が安定している場合にのみ機能します。 一度に新しいチェックアウトを表示し、次の訪問では古いチェックアウトを表示するユーザーがいる場合、サポートは問題を再現できず、分析はノイズが増し、ユーザーは信頼を失います。
解決策は簡単です。 安定した識別子とフラグキーに固有のハッシュを使用してユーザーをバケット化してください。 ユーザー ID は通常、適切な入力です。 匿名セッションでは、インストール ID またはデバイス ID を使用できます。 それがあれば。 Math.random() ブラウザ内では、ユーザーを予測不能に再割り当てするため、間違ったツールです。
実用的ロールアウトパスは次のようになります。
- 内部ユーザーとQAから始めてください。
- 小さなコホートにリリースしてください。
- エラー率、変換の影響、サポートチケットを確認した後、意図的に段階的に拡大する。
- フラグの全生涯で割り当てを固定しておく。
最後の点は簡単に過小評価される。スティッキーコホートは、実験のみに使われるものではない。スティッキーコホートは、インシデント対応を速める。エンジニアは、すぐに次の質問に答えることができる:どのユーザーが影響を受けたか?
実験を実行する場合は、サイズを確認する。Optimizelyのサンプルサイズ計算ツールは、トラフィックの量、基準変換率、最小検出可能効果が変数のユーザー数にどのように影響するかを示しています。Optimizelyサンプルサイズ計算ツールブラウザ外の段階的な更新の参考としては有用です。
__CAPGO_KEEP_0__ライブ更新の段階的なロールアウト phased rollouts for Capacitor live updatesターゲットリリースとリングベースのリリースは、破壊的な影響を最小限に抑える。
特定の機能は、ランダムなパーセンテージで始めるべきではありません。請求フロー、許可の求め、データの移行、ユーザーをロックアウトする可能性のあるものは、ターゲットリリースから始めるべきです。
ターゲットリリースは、最初のアウディエンスが既知の特性で定義されている場合に効果的です:特定のグループのユーザー
ターゲットリリースは、最初のアウディエンスが既知の特性で定義されている場合に効果的です:特定のグループのユーザー
- 内部スタッフによる内部テスト
- Betaテストに参加したユーザー
- 特定のアカウント階層
- 法律または言語要件が異なる地域
- 安全に機能をサポートするデバイスまたはアプリバージョン
リングベースのリリースにより、より効果的なターゲット設定が可能になる。リング0は従業員。リング1は信頼できる外部テスター。後続のリングは信頼性が向上するにつれて露出を拡大する。この構造は、リスクが明らかに不均等であることを認識しながら、すべてのユーザーを一つのプールとして扱う一般的な間違いを回避する。
このリリースモデルに合ったウォークスルーを埋め込むと良いでしょう:
リスクのある機能には、機能フロー全体を無効にするトップレベルのオペレーショナルフラグが必要です。
リリース前にキルSwitchを設計する:
アプリ起動初期段階で評価する。
- キャッシュした最後の安全な値をキャッシュする。
- __CAPGO_KEEP_0__
- __CAPGO_KEEP_0__が利用できない場合に安全なデフォルトを選択してください。
- 機能を無効にすることで、レンダリング以外の影響を防ぐことを確認してください。
- インシデントの際にフラグを切り替えることができるのは誰なのかをドキュメントしてください。
ウェブアプリのみの場合、リリースリスクを軽減します。モバイルやデスクトップのReactアプリの場合、修正されたビルドをユーザーに提供するまでの待ち時間を差し引くことができます。codeがすでにバンドルに含まれている場合、リモートフラグはロールバック戦略の一部になります。
テスト観測性とフラグ負債の管理
機能フラグの簡単な部分は、1つを追加することです。高価な部分は、多くのフラグが存在し誰もそのうちのどれがまだ重要かを覚えていないときに始まります。

各フラグは、信頼できる状態の数を倍増させる
マーティン・フラワーの警告はまだ当てはまります:機能フラグが存在する場合、チームは両方の検証を実行する必要があります オン オフ __CAPGO_KEEP_0__がすでにバンドルに含まれている場合、リモートフラグはロールバック戦略の一部になります。 states, and with multiple flags the possible state combinations grow combinatorially, which raises regression risk (Martin Fowlerによる機能フラグの説明).
Reactアプリケーションに直接影響することはあります:
- 条件付きレンダリングのパスが急速に広がります: 1つのページが複数のbranchを持つことができるのは誰も気づく前に:
- hydrationのミスマッチが起こりやすくなります: クライアントとサーバーが評価のタイミングが異なる場合に異議を唱えることができます:
- snapshotテストが単独で役に立たなくなります: ハッピーパスのレンダリングだけでは、フラグの反対の状態がテストされていない場合、ほとんどの情報が得られません:
実用的テストスタックは以下のようになります:
- ユニットテストで評価ロジックをテストすること:
- コンポーネントテストでフラグ付きのbranchをテストすること:
- リスクパスのみのエンドツーエンドカバレッジを追加します。
- デフォルトのフォールバックを明示的に検証します。
すべての組み合わせを目指すのではなく、ユーザーにダメージを与える可能性のある状態やレイアウトを破壊する可能性のある状態をテストします。
フラグの負債は実際に存在し、静かに高額になることがあります。
古いフラグは「code」の状態の腐敗と同じです。条件分岐、コメント、ダッシュボード、ランブックに残り、数ヶ月後誰かが「一時的な」ブランチを編集するのを忘れてしまいます。
実践で機能するクリーンアップルールは単純です:
| 問題 | 対処するべきこと |
|---|---|
| 所有者なし | フラグが作成されたときにチームまたは人を割り当てる |
| 終了状態なし | フラグが削除される、残る、または設定に変換されるかどうかを決定する |
| フラグが制御するのは多すぎる | フラグを小さく、狭いものに分割する |
| コアロジックはフラグの背後で隠されている | ビジネスロジックをレンダリング条件外に移動する |
クリーンアップルール: フラグには、所有者、目的、廃止計画が1日でなければならない
チームが「信頼」問題に陥るのはここです。フラグ名は存在しますが、フォールバックは間違っています。ダッシュボードのエントリが変更されたが、アプリタイプは変わっていません。code パスは死んでいるが、まだアクセス可能です。そのため、タイプ生成とレジストリ検証は、大規模システムでは、初期実装が単純に見えていても、重要です。
観察性は、フラグが役に立ったか、ただ存在したかを教えてくれる
ロールアウトは、フラグが完全に露出した時点で終わるのではなく、チームが何が起こったかを知る時点で終わる
少なくともこれらの質問を追跡する
- 露出 どのユーザーがどのバリアントを見たかを追跡する
- エラー: フラグされたパスがクライアントサイドのエラーを引き起こしたか?
- 採用: ユーザーが公開された機能を使用したか?
- ロールバック信号: どの閾値で機能をオフにするか?
フラグプラットフォームが回答しない場合、リリースレビュー中でもまだ推測することになる。
CI/CDを使用したフラグのセキュリティと自動化
悪いデプロイは明らかだ。フラグの変更は、静かに、そして場合によっては危険に近い、生産行動を変更することなく、codeの同様のレビュー経路を通過しない。

フラグの変更を生産の変更と同じように扱え
機能フラグはリリースの制御である。チームが生産でフラグを切り替えることができる場合、そのチームはユーザーが受け取るもの、codeのパスが実行されるもの、そして場合によっては、どの統合が発火するかを変更できる。そうした権限は、デプロイアクセスと同じ規制を必要とするものである。
The minimum controls are straightforward:
- ロールベースのアクセス制御: 生産フラグの変更を許可するのは誰かを制限し、読み取りアクセスと編集アクセスを分離する。
- 監査ログ: フラグの変更を記録するには、誰が変更したか、いつ変更したか、どの環境を変更したかを明確に記録する。
- 環境隔離: ステージング、プレビュー、生産フラグは異なるべきであり、テスト変更がライブトラフィックに影響しないようにする。
- サーバーサイドのチェックが敏感な決定に必要: クライアントフラグはUIを隠すことができるが、請求アクセス、特権、認証にはならない。
フラグダッシュボードを共有スプレッドシートのように扱うのはよくない。製品は顧客に何かを有効にする。サポートは不満を止めるためにそれを無効にする。エンジニアは誰も触っていないと仮定する。デプロイがないからだ。そうした設定は、インシデントを説明する必要があるまで機能する。
バンドルアプリはリスクを高める。ウェブアプリでは、codeの修正は迅速に配信できる。Capacitorまたはデスクトップアプリでは、codeの破損がすでにデバイスに置かれている可能性がある。codeでReactモバイルアプリを構築するチームは CapacitorでReactモバイルアプリを構築するチームは ロールバックはしばしば機能を無効にすることになるため、承認ルールを厳しくする必要がある。
フラグ操作をパイプライン内に含める
フラグが外部に存在する場合、信頼性が低くなる。安全なパターンは、機能を配信するワークフローと同様に管理することである。
つまり、
- Create or update flags in the same PR as the feature code
- CIでリモートレジストリとタイプ付きフラグ定義を検証する
- 環境ごとにデフォルト値を意図的に設定する
- 必要なフラグが欠落または不正な場合、リリースをブロックする
- 期限切れまたはロールアウト終了状態のフラグに対してクリーンアップタスクをスケジュールする
生産障害がフラグによって引き起こされる可能性がある場合、CIはリリース前にセットアップを検出できるようにする。そうするには、デフォルト値が欠落している、キー名が変更されている、環境マッピングが古い、またはコントロールプレーンに存在しないがcodeに存在するフラグなどを検出する必要がある。
パイプライン構造の基準点として利用する必要がある場合、 Git Actions CI/CD ワークフロー ビルドチェック、デプロイゲート、自動化ステップの拡張可能なフラグ検証用の堅牢な参照です。
秘密を守り、SDKの選択肢を面白くする
フロントエンドチームは、フラグのセキュリティを過度に複雑にし、明らかな部分を無視することがあります。一般に、ブラウザで設計されたクライアントサイドのSDKキーは通常問題ありませんが、管理者トークン、書き込みクレデンシャル、環境管理キーはCIまたはバックエンドサービスのみに属します。
実用的分割は簡単です。プレゼンテーション変更や低リスクの実験用にクライアントサイド評価を使用し、価格、許可、敏感なフローへのキルSwitch、ローカルJavaScriptに信頼できないものを含むすべてのものにサーバーサイド評価を使用します。
その境界は、遅いリリース環境ではより重要です。Webチームは迅速なデプロイで回復できますが、モバイルおよびデスクトップチームは、フラグシステムを回復機構として使用する必要があります。正しい人がプロダクションフラグを編集できる場合、またはCIがフラグ契約を検証しない場合、ロールバックは迅速に混乱することになります。
Web Feature Flags for Capacitor とモバイル アプリケーション
ほとんどの React フィーチャーフラグの記事は、即座に再デプロイできるWebアプリを前提としています。この仮定は、React code が Electron、または別のバンドルされたランタイム内に存在するときに破棄されます。 Capacitor, Electron, または別のバンドルされたランタイム。
バンドルされたアプリはリリースの計算を変えます
Inハイブリッドアプリでは、ユーザーがすぐに更新しないbundle内にJavaScript、CSS、アセット、configを配信することがよくあります。機能はすでにデバイス上に存在している場合、ユーザーが機能を使用する前に変更する必要があります。これはフラグの役割を完全に変えることになります。
ハイブリッドリリース戦略に関する最近の議論では、CapacitorまたはElectronアプリのリリースリスクモデルに対する既存のReactフラグコンテンツがほとんど存在しないことが指摘されました。そうしたチームにとって、主なニーズは、フラグ、ターゲットチャンネル、ロールバック保護を組み合わせたリリースオーケストレーション層の実装です。特に、ストアレビューの遅延を回避する必要がある場合、単純なオン/オフスイッチではありません。ハイブリッドアプリリリースリスク議論).
正解です。バンドルされたアプリでは、フラグは条件付きレンダリングよりも すでに配信された機能の遠隔アクティベーション.
モバイルまたはデスクトップのReactアプリでは、フラグはUIの存在よりもリリースタイミングを制御することが多いです。
これはまた、チャンネルベースの配布の重要性を示しています。ハイブリッドアプリを構築している場合、そしてアプリシェルプラスWebcodeリリースモデルが一緒に機能するようにしたい場合は Reactモバイルアプリの作成Capacitor 実用的な開始点です。
フラグは、更新配信と組み合わせることが最も効果的です。
モバイルおよびデスクトップチームにとって、フラグだけではすべてのリリース問題を解決することはできません。フラグはcodeパスを非表示または有効にすることができますが、既にバンドル内のバグを修正したアセットやロジックを配信することはできません。
そのため、より強力なモデルは:
- codeの更新をフルストアサイクル外で配信することができるように、プラットフォームが許可する限り、
- __CAPGO_KEEP_0__の更新をチャネルまたは対象者にターゲットする
- および、活性化、ロールバック、ステージドエクスポージャーを制御するフラグを使用する
使用するとともに、ライブ更新とフラグはハイブリッドチームにウェブスタイルのリリース制御の近いものを与える。 それが必要なのは、 discipline だけではない。
チームがCapacitorまたはElectronアプリを配信し、リリース制御層が必要な場合、 Capgo は、ターゲットされたチャネルに署名されたウェブバンドルを配信し、ロールバック保護と観察性をサポートし、機能フラグがライブ更新と共に機能する必要があるハイブリッドアプリワークフローに適合する。
React Feature Flags: A Complete Implementation Guide
React Feature Flags: A Complete Implementation Guide を使用してチャネルルーティングとステージドロールアウトを計画している場合、__CAPGO_KEEP_0__を__Channels__と接続する __Channels__ __CAPGO_KEEP_0__ __CAPGO_KEEP_0__の実装詳細については、 __CAPGO_KEEP_1__ __CAPGO_KEEP_0__の実装詳細については、 __CAPGO_KEEP_1__ __CAPGO_KEEP_0__の実装詳細については、 ベータテスト ソリューション __CAPGO_KEEP_0__の製品ワークフローについては、ベータテスト ソリューション、 バージョン ターゲット ソリューション __CAPGO_KEEP_0__の製品ワークフローについては、バージョン ターゲット ソリューション。