跳过主要内容
移动 CI/CD Capacitor

React 特性标志: 完整实现指南

了解如何使用我们的完整指南实现 React 特性标志。涵盖架构模式、发布策略、CI/CD 和现代应用程序的最佳实践。

内容营销

上下文: Capgo 营销网站。角色: 短 UI 标签或导航项。见于: 组件 BlogAuthorByline.astro。消息键 `content_marketer` (Content Marketer)。

That feeling is usually the first sign that your React app has outgrown simple deploys. Once a product has real users, a release stops being just a technical event. It becomes a risk decision. If the new search UI breaks, if the checkout variant confuses users, or if a mobile build ships code you can’t quickly undo, you need more than if (process.env.NODE_ENV) 希望

这种感觉通常是 React 应用程序超出了简单部署的第一个迹象。一旦产品有了真正的用户,发布就不再仅仅是一个技术事件。它变成了一个风险决策。如果新搜索 UI 破坏了,如果检出变体混淆了用户,或者如果移动构建部署了 __CAPGO_KEEP_0__ 您无法快速撤销,则需要更多的 和希望。 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 特性标志开始发挥作用。不是作为组件中的可爱布尔值,而是作为一个发布控制层,让您可以单独部署 __CAPGO_KEEP_0__ 而不暴露它。在 Web 应用程序中,这意味着更安全的发布。在捆绑应用程序中,如 __CAPGO_KEEP_1__ 或 Electron,它们更重要,因为回滚速度受限于商店审查、安装延迟和更慢的发布周期。

为什么特性旗子对于现代React应用至关重要

周五下午发布。新账单摘要UI已经部署,支持团队有一个启动清单,一个企业客户仍然需要旧流程,直到周一。在一个Web应用中,这已经很紧张。在一个通过桌面安装器或移动商店分发的捆绑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.

一个标题为《为什么特性标志对于现代React应用至关重要》的图表,解释了部署策略和好处。

部署和发布是不同的工作。

部署回答,“code是否在生产环境中?”发布回答,“谁可以现在执行这个行为?”

一旦React应用有真正的流量、多个环境和影响收入、权限或导航的特性,区分这些概念就变得很重要。团队可以合并早期、在生产环境中测试内部小组,并只在他们信任行为时才扩大访问。对于像Capacitor应用、Electron应用和商店审查的移动构建这样的慢速发布平台,这种控制就更有价值了,因为二进制文件可能已经在用户的手中了,而功能还没有准备好供所有人使用。

一个标志在三个常见情况下都有帮助:

  • 受控发布: 首先暴露一个新路径给一个小组
  • 实验: 比较变体而不维护单独的部署
  • 快速关闭: 禁用一个风险特性而不等待新构建

A simple rule works well here. If a production issue would be expensive to reverse, ship that code behind a flag.

新加入旗帜的团队通常会停留在UI条件上。 flag ? <NewUI /> : <OldUI /> 这是可见的部分,但这不是有趣的部分。其核心价值在于运营。远程配置、确定性目标和快速关闭特性的能力使旗帜在生产环境中有用。如果您的React应用还需要应用级的运行时设置,一个 远程配置插件用于Capacitor应用 适用于__CAPGO_KEEP_0__应用

旗帜不再有用时

我在成长中的前端代码库中看到相同的失败模式。团队快速添加旗帜,环境之间的名称漂移,fallback值隐藏配置错误, nobody知道“开”是否意味着全局开启,仅限员工开启,还是仅限测试环境开启。在这种情况下,旗帜系统开始创造风险而不是减少风险。

类型安全有帮助,但它解决不了整个问题。团队仍然需要一个清晰的注册表、所有权和一致的方式来评估旗帜跨应用。否则,React组件会在推出或部分回滚时出现局部假设,这些假设会破坏。

区别很容易看出:

使用场景 弱版本 强版本
UI切换 组件本地布尔值 拥有者和发布规则的远程标志
发布安全 手动部署回滚 通过远程配置立即禁用
实验 临时分支比较 稳定分组分配和可测量曝光

React特性标志的重要思维转变很简单。它们属于您的发布过程,而不仅仅是您的JSX。以这种方式对待它们,尤其是在发布速度慢的应用程序中,它们成为生产环境混乱时减少爆炸半径的少数工具。

在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 flag methodology).

在 Capgo 中,这会影响你的 code 应该存放的位置。将标志加载放在应用程序根部。简化标志的使用。避免在叶子组件内部获取标志。

A practical shape looks like this:

  1. Load or hydrate flags before the main tree renders.
  2. React标志方法论
  3. 通过一个钩子或一个包装器模式阅读它们。
  4. 将评估逻辑从展示组件中分离出来。

如果您需要一个远程配置层来管理应用级设置以及标志,则一个工具,如 Capacitor 远程配置插件 与混合 React 应用中的此模式自然相配。

模式一:使用 React 上下文和一个自定义钩子

这是我通常推荐的默认模式。它明确、可测试,并且如果您切换供应商后迁移起来很容易。

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>;
}

因为您的组件只要求一个最终答案。它们并不关心答案是如何计算出来的。

模式二:使用高阶组件

高阶组件 A 当您想在整个屏幕、路由元素或遗留类组件上设置门控时,它很有用,而不必在各处添加hook调用。

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中的hook更容易跟踪,而HOC在DevTools中的组件树可能会变得更杂乱。然而,对于路由级门控,它们仍然很干净。

不要让组件决定推出策略。组件应该消费标志结果,而不是实现分桶、用户目标或缓存刷新规则。

React特性标志模式比较

标准 上下文+hook 高阶组件(HOC)
最佳用途 组件级别的决定和变体 包裹整个页面、路由或遗留组件
灵活性 高级 中级
开发者体验 在现代函数组件中表现出色 当钩子不方便使用时很有用
包清晰度 清晰的导入和直接读取 树结构中的更多抽象
测试 通过提供商轻松模拟 包裹的集成案例
长期维护性 通常更好 适用于适度使用

如果您第一次实现 React 特性标志,请从 上下文 + 钩子. 只有在您有特定的需要时才添加 HOC。

实施回滚和回滚策略

在特性发布后出现问题时,回滚计划最为重要。 UI 可能只显示新按钮或屏幕,但关键任务是决定谁先看到它、暴露速度如何以及如何快速关闭它而不等待重新部署。即使在 React 应用程序内置于移动或桌面捆绑包中,也更为重要,因为回滚取决于远程配置,因为应用商店审查或桌面分发需要时间。

软件特性标志从内部到全球发布的回滚和回滚策略的漏斗图表。

百分比回滚需要粘性分配

百分比回滚只有在分配稳定时才有效。如果同一用户在一次访问时看到新结帐界面,在下一次访问时看到旧界面,支持人员无法复制问题,分析数据变得杂乱,用户信任会丧失。

解决方案很简单。使用稳定的标识符加上标志键的确定性哈希来分桶用户。用户 ID 通常是正确的输入。匿名会话可以使用安装 ID 或设备 ID 如果您有一个。 Math.random() 在浏览器中是错误的工具,因为它会不确定地重新分配用户。

A rollout路径看起来像这样:

  • 首先使用内部用户和QA。
  • 将其发布到一个小的试验组。
  • 在检查错误率、转化率和支持票后,逐步扩大。
  • 在旗帜的整个生命周期中保持分配。

最后一点容易低估。粘性小组不仅适用于实验。它们使事故响应更快,因为工程师可以立即回答一个基本问题:哪些用户暴露了?

如果您运行实验,务必在发布之前确定样本大小。Optimizely的样本大小计算器显示了流量量、基准转化率和最小可检测效果如何影响每个变体所需的用户数量(Optimizely样本大小计算器)。

没有进行此检查,团队经常将噪音误认为是信号,并提前推广功能。 phased rollouts for Capacitor live updates__CAPGO_KEEP_0__阶段性发布的live updates

目标和环形发布减少爆炸半径

某些功能不应以随机百分比开始。计费流程、权限提示、数据迁移以及任何可能锁定用户的功能通常需要目标发布

目标发布在以下情况下效果最佳:

  • 内部员工进行内部测试
  • 同意存在bug的beta测试者
  • 特定账户等级
  • 具有不同法律或语言要求的地区
  • 支持该功能的设备或应用版本

环形发布使目标发布更具操作性。环0是员工。环1是信任的外部测试者。随后环的暴露范围扩大,信心增强。这一结构有助于团队避免将风险明显不均衡的用户视为一个池

以下是嵌入式教程,配套此发布模型:

杀switch是旗帜的价值所在

每个风险功能都需要快速脱离路径。在实践中,这通常意味着一个顶级操作性旗帜,禁用整个功能流,而不是一个仅隐藏一个入口点的显示旗帜,而背景请求、效果或导航路径仍在运行

在发布前设计杀switch:

  • 尽早在应用启动时评估它。
  • 缓存最后一次安全值。
  • 如果标志服务不可用时选择一个安全的默认值。
  • 确保禁用功能不会产生副作用,而不是仅仅停止渲染。
  • 在事故期间,记录谁可以翻转它。

对于仅限Web应用,这减少了发布风险。对于移动和桌面React应用,它可以是区分轻微事故和等待用户获取修复版本的差异。如果code已经在捆绑包中发布,远程标志就成为回滚策略的一部分,而不是仅仅是发布策略。

测试可观察性和管理标志债务

添加特性标志的容易部分是添加一个。然而,当有很多标志时,很难记住哪些仍然重要。

一间现代化的服务器房,装有闪烁的灯和有序的网络线。

每个标志都增加了你必须信任的状态数量

马丁福勒的警告仍然有效:一旦存在特性标志,团队必须验证两种状态 On 和 Off 状态为开启和关闭时,多个标志的可能组合状态会呈指数增长,这增加了回归风险(Martin Fowler关于特性开关的说法)对React应用程序而言,这有直接后果:).

条件渲染路径会迅速扩散:

  • 一个页面可以有多个branch在任何人注意到之前 脱水不匹配变得容易触发:
  • 客户端和服务器可能会因为评估时间不当而产生分歧 快照测试变得单独不太有用:
  • 一个happy-path渲染并不能告诉你很多,如果相反的标志状态没有测试 快照测试变得单独不太有用:

A实践测试堆栈看起来像这样:

  1. 测试评估逻辑的单元测试。
  2. 测试带有标记的分支的组件测试。
  3. 仅对风险路径添加端到端覆盖。
  4. 明确验证默认回退。

不要追求每种组合。通常会在自己的重量下崩溃。测试那些可能伤害用户或破坏布局的状态。

标记债务是真实的,它会悄悄地变得昂贵。

旧标记变成了code的腐烂形式。它们留在条件语句、注释、仪表板和操作手册中。然后有人几个月后编辑“临时” branch,因为没有人移除它。

在实践中有效的清理规则很简单:

问题 做什么
无主 为标志创建时分配团队或人员
没有结束状态 决定标志是否删除、保留或转换为配置
标志控制太多 将其分解为更小、更窄的标志
核心逻辑隐藏在标志后面 将商业规则从渲染条件语句中移出

清理规则: 每个标志都应有一个拥有者、一个目的和一个删除计划

这也是团队被“信任”问题所伤害的地方。标志名称存在,但fallback是错误的。仪表板条目发生了变化,但应用类型没有。code路径已经死亡,但仍然可达。因此,类型生成和注册表验证在更大的系统中很重要,即使初始实现看起来很简单。

可观察性告诉你标志是否有帮助还是只是存在

滚动部署不仅仅是标志达到最大暴露度。它是完成的,当团队知道发生了什么时

至少关注这些问题:

  • 曝光度: 哪些用户看到哪个变体?
  • 错误: 标记路径触发更多客户端故障吗?
  • 采用率: 用户是否使用您暴露的功能?
  • 回滚信号: 什么阈值会让您关闭它?

如果您的标记平台无法回答这些问题,您将在发布审查期间仍然猜测。

保护您的标记并使用CI/CD自动化

一个坏的部署很明显。一个坏的标记更改更静默,甚至在某些情况下更危险,因为它改变了生产行为,而不经过同样的审查路径code。

使用CI/CD流程和工具来保护功能标志并自动化工作流程的示意图。

对旗帜变更进行生产变更处理

Feature flags are release controls. If a team can flip a flag in production, that team can change what users get, what code paths run, and sometimes which integrations fire. That deserves the same discipline as deploy access.

最低控制措施很简单:

  • 基于角色的访问控制: 限制谁可以更改生产标志,并分离读取访问权限和编辑访问权限。
  • 审计日志: 记录谁改变了标志、什么时候改变以及他们触摸了哪个环境。
  • 环境隔离: 预发布、预览和生产标志应该是不同的,以便测试更改不会影响在线流量。
  • 服务器端检查敏感决策: 客户端标志可以隐藏UI,但不应该决定计费访问、权利或授权。

A种常见的错误是将标志仪表板视为共享的电子表格。产品为客户打开某个功能。支持人员关闭它以停止抱怨。工程人员假设没有人触摸它,因为没有发布。这种设置直到需要解释一个事件才会出现问题。

嵌入式应用程序提高了风险。在Web应用程序中,一个code修复可以快速发布。在Capacitor或桌面应用程序中,可能已经在设备上等待远程标志暴露的code可能已经损坏。构建 React mobile apps with Capacitor React移动应用程序的

__CAPGO_KEEP_0__

应更加严格地遵守审批规则,因为回滚通常意味着禁用已发布的功能而不是替换二进制文件。

将标志操作放入管道中

  • 在同一 PR 中创建或更新标志,同期与特性 code
  • 这通常意味着:
  • 在同一个PR中创建或更新标志和功能__CAPGO_KEEP_0__
  • 在CI期间验证类型化的标志定义与远程注册表
  • 根据目的在每个环境中设置默认值

我认为一个简单的规则是:如果生产事故可能是由标志引起的,CI应该能够在发布之前捕获设置。包括缺失的默认值、重命名的键、陈旧的环境映射和标志存在于code但不在控制平面中的标志。

如果您需要一个管道结构的起点,请 Git Action CI/CD 工作流 是构建检查、部署门槛和自动化步骤的参考,用于扩展标志验证。

保留机密和SDK选择的枯燥

前端团队有时会对标志安全性进行过度复杂化,并忽略了明显的部分。公共客户端SDK密钥通常是安全的,如果供应商为浏览器使用而设计。管理员令牌、写入凭证和环境管理密钥不属于此类。它们应该只在CI或后端服务中使用。

实践上的分界线很简单。使用客户端评估进行呈现更改和低风险实验。使用服务器端评估进行定价、权限、敏感流程中的杀switch和您不信任本地JavaScript的任何内容。

这个界限在较慢的发布环境中更为重要。Web团队可以通过快速部署恢复。移动和桌面团队通常需要标志系统作为恢复机制。如果错误的人可以编辑生产标志,或者CI从未验证标志契约,回滚会迅速变得混乱。

超越Web特性标志Capacitor和移动应用

Most articles about react feature flags assume a web app that can redeploy instantly. That assumption breaks the moment your React code lives inside Capacitor, Electron或

另一个捆绑的运行时中

就打破了。

A recent discussion around hybrid release strategy pointed out that existing React flag content rarely addresses the release-risk model for Capacitor or Electron apps. For those teams, the primary need is a release orchestration layer that combines flags, targeted channels, and rollback protection instead of a simple on/off switch, especially when avoiding store review delays matters (混合应用发布风险讨论).

最近关于混合发布策略的讨论指出,现有的 React 标志内容很少涉及__CAPGO_KEEP_0__或Electron应用的发布风险模型。对于这些团队,主要需求是一个结合标志、目标渠道和回滚保护的发布协调层,而不是简单的开关,尤其是避免商店审查延迟很重要( 混合应用发布风险讨论.

在移动或桌面端的React应用中,标志通常控制发布时间而不是UI的显示。

This is also why channel-based distribution matters. If you’re building hybrid apps and need the app shell plus web code release model to make sense together, 使用 Capacitor 创建 React 移动应用 是一个实用的起点。

标志在配对更新时最有效

对于移动和桌面团队来说,标志本身无法解决每个发布问题。它们可以隐藏或启用 code 路径,但无法替代在捆绑中修复的固定资产或逻辑。

因此更强大的模型是:

  • 在您的平台允许的情况下,分发 code 更新,避免每次全局商店周期
  • 针对特定渠道或受众
  • 并使用标志来控制激活、回滚和阶段性曝光

一起使用实时更新和标志,混合团队可以获得类似于 web-style 的发布控制。这种方法并没有消除对纪律的需求。它只是给了你更多的控制手段,当出现问题时。


如果您的团队发布 Capacitor 或 Electron 应用,并需要发布控制层 Capgo 是您可以考虑的选项之一。它将签名的 web捆绑分发到目标渠道,支持回滚保护和可观察性,并适合混合应用工作流程,其中特性标志需要与实时更新一起工作,而不是替代它们。

继续React特征标志:全面实现指南

如果您正在使用 React特征标志:全面实现指南 来规划频道路由和阶段性发布,请将其与 频道 context 频道 context 频道 context 频道 为 Beta Testing Solution 产品工作流程中的 版本目标解决方案 为版本目标解决方案中的产品工作流提供

实时更新Capacitor应用

当Web层级别的bug活跃时,通过Capgo将修复发送给用户,而不是等待几天的应用商店审批。用户在后台接收更新,而原生变化保持在正常的审批路径中。

最新博客

Capgo 为您提供创建真正专业的移动应用所需的最佳见解。