
后端前端【免费下载链接】flagsmithFlagsmith is an open-source feature flag platform with remote config, experimentation, and self-hosted or cloud deployment options.项目地址https://gitcode.com/gh_mirrors/fl/flagsmith点击查看免费下载本文基于 Flagsmith 官方 React SDK 文档系统讲解如何在 React 与 React Native 应用中通过FlagsmithProvider、useFlags、useFlagsmith、useFlagsmithLoading四个核心 API 完成特性开关Feature Flags与远程配置Remote Config的接入、用户识别Identify与 Trait 管理并补充 SSR/Next.js 场景下的服务端状态水合方案帮助你在客户端应用中实现精准、低重渲染的灰度发布能力。Flagsmith React SDK 与 JavaScript SDK 共享同一套底层实现其最大特点是提供了 React/React Native Hooks允许你只订阅关心的 feature 与 trait从而限制不必要的组件重渲染。本文所有代码均可直接复制运行初始化参数细节以 JavaScript SDK 初始化选项 为准。安装通过 NPM 安装React / Webnpm i flagsmith/flagsmith --save通过 NPM 安装React Nativenpm i flagsmith/react-native --save:::tipReact Native SDK 与普通 React SDK 共享完全相同的 Flagsmith 实现但需要额外提供一个AsyncStorage实现例如react-native-community/async-storage以便启用 analytics 与本地缓存能力。具体见 JavaScript SDK 初始化选项 中AsyncStorage参数的说明。:::基本用法SDK 针对单个环境Environment初始化。你可以在 Flagsmith 后台的 Environment 设置页面找到你的 Client-side Environment Key。Step 1用 FlagsmithProvider 包裹你的应用用FlagsmithProvider组件包裹应用它会为整个应用提供 React Context使useFlags与useFlagsmith两个 Hook 在任意子组件中可用。import flagsmith from flagsmith/flagsmith import {FlagsmithProvider} from flagsmith/flagsmith/react export function AppRoot() { FlagsmithProvider options{{ environmentID: YOUR_ENVIRONMENT_KEY, }} flagsmith{flagsmith} {...} /FlagsmithProvider };向 Provider 传入options会触发客户端的初始化这些选项的完整 API 参考见 JavaScript SDK 初始化选项。:::tip 在渲染 FlagsmithProvider 之前初始化如果你希望在 React 渲染之前例如在 redux 中或 SSR 场景下就完成 Flagsmith 客户端初始化可以先调用 flagsmith.init此时不要再向FlagsmithProvider传入options属性二者选其一即可。:::Step 2使用 useFlags 读取 feature 值与 enabled 状态被FlagsmithProvider包裹的组件可以通过useFlagsHook 读取 feature 的值、enabled 状态以及用户 traitimport { useFlags } from flagsmith/flagsmith/react; export function MyComponent() { const flags useFlags([font_size], [example_trait]); // only causes re-render if specified flag values / traits change return ( div classNameApp font_size: {flags.font_size.value} example_trait: {flags.example_trait} /div ); }useFlags的返回值可以直接按键名访问flags.font_size.value对应远程配置的值flags.example_trait对应已识别用户的 trait 值。useFlags API ReferenceuseFlags(requiredFlags:string[], requiredTraits?:string[]) {[key:string]: IFlagsmithTrait or IFlagsmithFeature}requiredFlags: string[]必填声明你关心的 feature 名称列表只有这些 feature 的值发生变化时组件才会重渲染requiredTraits?: string[]可选声明你关心的 trait 名称列表只有这些 trait 发生变化时组件才会重渲染。IFlagsmithTrait与IFlagsmithFeature的精确定义位于 SDK 的types.d.ts类型文件中。FlagsmithProvider API ReferencePropertyDescriptionRequiredDefault Valueflagsmith: IFlagsmithDefines the flagsmith instance that the provider will use.YESnulloptions?: IInitConfigInitialisation options to use. If you dont provide this you will have to call flagsmith.init elsewhere.nullserverState?: IStateUsed to pass an initial state, in most cases as a result of SSR flagsmith.getState(). See Next.js and SSRnull三个属性的使用要点flagsmith为必填是 Provider 内部所有 Hook 依赖的客户端实例options与手动调用flagsmith.init()二选一若你已经在 SSR/Redux 中初始化过就不要重复传入serverState专用于 SSR 场景把服务端flagsmith.getState()的结果传给客户端避免客户端首屏重复请求 flags。Step 3使用 useFlagsmith 访问 Flagsmith 实例被包裹的组件可以通过useFlagsmithHook 直接拿到 SDK 实例从而调用identify、logout、setTrait、getValue等命令式 APIimport React from react; import { useFlags, useFlagsmith } from flagsmith/flagsmith/react; export function MyComponent() { const flags useFlags([font_size], [example_trait]); // only causes re-render if specified flag values / traits change const flagsmith useFlagsmith(); const identify () { // This will re-render the component if the user has the trait example_trait or they have a different feature value for font_size flagsmith.identify(flagsmith_sample_user); }; const logout () { // This will re-render the component if the user has the trait example_trait or they have a different feature value for font_size flagsmith.logout(); }; return ( div classNameApp font_size: {flags.font_size?.value} example_trait: {flags.example_trait} {flagsmith.identity ? button onClick{logout}Logout/button : button onClick{identify}Identify/button} /div ); }上例展示了完整的「识别用户 → 读取个性化 flags → 退出识别」闭环点击 Identify 调用flagsmith.identify(flagsmith_sample_user)SDK 会为该用户拉取专属 flags 与 traits当flagsmith.identity存在时切换为 Logout 按钮点击后调用flagsmith.logout()回到环境默认值。useFlagsmith API Reference该 Hook 用于访问FlagsmithProvider内部使用的 SDK 实例useFlagsmith() IFlagsmithuseFlagsmithLoading API Reference该 Hook 用于访问 SDK 加载状态useFlagsmithLoading() LoadingStateLoadingState的类型定义如下可用于区分当前 flags 数据来自默认值、本地缓存还是服务端export declare enum FlagSource { NONE NONE, DEFAULT_FLAGS DEFAULT_FLAGS, CACHE CACHE, SERVER SERVER, } export declare type LoadingState { error: Error | null; // Current error, resets on next attempt to fetch flags isFetching: bool; // Whether there is a current request to fetch server flags isLoading: bool; // Whether any flag data exists source: FlagSource; //Indicates freshness of flags };初始化选项详解React 场景常用FlagsmithProvider的options本质就是flagsmith.init()的入参以下是 React 开发中最常用的几个选项完整表格见 JavaScript SDK 初始化选项PropertyDescriptionRequiredDefault ValueenvironmentID: string指定要获取 flags 的项目环境例如 ACME 项目 - Staging。YESnullonChange?: (previousFlags, params, loadingState) voidflags 检索完成后的回调(previousFlags,{isFromServer, flagsChanged, traitsChanged}){...}。YESnullonError?: (res:{message:string}) voidflags 检索失败的回调。nullrealtime?: boolean是否监听实时 flags 更新事件Server Sent Events。falsecacheFlags?: boolean是否将 flags 缓存到本地存储下次启动先读缓存再请求 API。nullcacheOptions?: {ttl?:number, skipAPI?:boolean, loadStale?:boolean}缓存 TTL毫秒0 表示永久、是否在有缓存时跳过 API、以及是否无条件使用过期缓存。{ttl:0, skipAPI:false, loadStale:false}enableAnalytics?: boolean是否为 getValue/hasFeature 评估开启 flag analytics。falsedefaultFlags?: {flag_name: {enabled: boolean, value: string/number/boolean}}定义默认 flags首次从服务端获取后会被覆盖用于 API 不可用时的兜底。nullpreventFetch?: boolean禁止初始化时拉取 flags改为稍后手动调用 getFlags。falsestate?: IState设置预定义状态适用于 SSR/同构应用。falseapi?: string自定义 API 地址自托管 Flagsmith 时必填。https://edge.api.flagsmith.com/api/v1/eventSourceUrl?: string自定义实时 flags 更新事件SSE地址自托管时使用。https://edge.api.flagsmith.com/api/v1/identity?: string在首次 API 调用时指定身份直接拉取该用户的 flags。YESnulltraits?: Recordstring, string/number/boolean首次 API 调用时随身份一并发送的 traits可用于 segment 覆盖。YESnull提供默认 flags离线兜底为了让应用在 API 不可达时依然按预期工作可以定义默认 flag 值详见 defensive coding 最佳实践 相关章节import flagsmith from flagsmith/flagsmith or flagsmith/react-native; try { flagsmith.init({ environmentID: YOUR_CLIENT_SIDE_ENVIRONMENT_KEY, defaultFlags: { feature_a: { enabled: false}, font_size: { enabled: true, value: 12 }, } onChange: (oldFlags, params) { ... }, }); } catch (e) { // if an exception is thrown the default values will be used }Default Flag Offline HandlerCI/CD 离线 flags你还可以借助 legacy CLI 在构建流水线中自动生成默认 flags 文件安装 legacy CLInpm i flagsmith/cli --save-dev在 npm postinstall 阶段调用 CLI 生成flagsmith.json每次npm install时更新环境变量方式export FLAGSMITH_ENVIRONMENTYOUR_CLIENT_SIDE_ENVIRONMENT_KEY flagsmith get手动指定flagsmith get YOUR_CLIENT_SIDE_ENVIRONMENT_KEY应用中用生成的 JSON 初始化flagsmith.init({environmentID: json.environmentID, state:json})这样在尝试本地存储或请求 API 之前默认 flags 就已就绪。用户识别与 Trait 管理识别用户允许你在 Flagsmith 后台针对特定用户配置 features 与 traits。你可以在初始化时或初始化之后调用flagsmith.identify初始化之后再调用会重新从 API 拉取该用户的 flags。示例初始化后识别用户未带身份初始化时客户端拉取的是环境默认 flags除非传入preventFetch:trueimport flagsmith from flagsmith/flagsmith; flagsmith.init({ environmentID: YOUR_CLIENT_SIDE_ENVIRONMENT_KEY, onChange: (oldFlags, params) { const { isFromServer } params; // 判断更新来自服务端还是本地缓存 // 为身份设置 trait flagsmith.setTrait(favourite_colour, blue); // 会保存到用户可用 flagsmith.getTrait 查询 // 检查 feature if (flagsmith.hasFeature(my_power_user_feature)) { myPowerUserFeature(); } // 检查 trait if (!flagsmith.getTrait(accepted_cookie_policy)) { showCookiePolicy(); } // 或读取 feature 值 const myPowerUserFeature flagsmith.getValue(my_power_user_feature); // 对比旧值判断是否发生变化 const myPowerUserFeatureOld oldFlags[my_power_user_feature] oldFlags[my_power_user_feature].value; if (myPowerUserFeature ! myPowerUserFeatureOld) { // Do something! } }, }); /* 可在 init 完成后调用也可在 init 时通过 identity/traits 属性一并传入避免 flags 被拉取两次。 */ flagsmith.identify(flagsmith_sample_user); // 若该用户不存在会在后台自动创建示例初始化时直接指定用户在init时传入identity属性客户端会直接拉取该用户的 flags 而非环境默认值同时传入的traits可能基于 segment 覆盖决定返回哪些 flagsimport flagsmith from flagsmith/flagsmith; flagsmith.init({ environmentID: YOUR_CLIENT_SIDE_ENVIRONMENT_KEY, identity: flagsmith_sample_user, traits: { age: 21, country: England }, // 这些会追加到用户已有 traits onChange: (oldFlags, params) { const { isFromServer } params; flagsmith.setTrait(favourite_colour, blue); if (flagsmith.hasFeature(my_power_user_feature)) { myPowerUserFeature(); } const myPowerUserFeature flagsmith.getValue(my_power_user_feature); const myPowerUserFeatureOld oldFlags[my_power_user_feature] oldFlags[my_power_user_feature].value; if (myPowerUserFeature ! myPowerUserFeatureOld) { } }, });常用命令式 APIFunctionDescriptioninit(initialisationOptions) Promisevoid针对某个环境初始化 SDKhasFeature(key:string) boolean查询 feature 是否开启如flagsmith.hasFeature(powerUserFeature) // truegetValueT(key:string, {json?:boolean, fallback?:T})读取 feature 值如flagsmith.getValue(font_size, { fallback: 12 }) // 10json:true时自动按 JSON 解析getTrait(key:string)读取已识别用户的 trait 值getAllTraits() Recordstring, string/number/boolean获取已识别用户的全部 traitsgetState() IState获取当前状态用于 Next.js / 同构应用setState(state: IState) void设置当前状态用于 Next.js / 同构应用setTrait(key, value) PromiseIFlags为已识别用户设置 traitsetTraits(values) PromiseIFlags批量设置 traitsvalue 传 null 表示删除该 traitincrementTrait(key, value:number) PromiseIFlags对数值型 trait 做增减如flagsmith.incrementTrait(click_count, 1)startListening(ticks1000) void每 x 毫秒轮询 API 获取 flags 变化stopListening() void停止轮询getFlags() PromiseIFlags手动拉取环境或已识别用户的 featuresgetAllFlags() IFlags返回当前全部 flagsidentify(userId, traits?) PromiseIFlags识别用户可选 traits会触发 getFlagslogout() PromiseIFlags退出身份识别触发 getFlags 回到环境默认值SSR 与 Next.js通过 serverState 水合客户端在 React 场景中FlagsmithProvider的serverState属性专为 SSR 设计。完整的服务端流程是在服务端调用 flagsmith.init可携带 identity拉取 flags通过 flagsmith.getState() 将结果状态传给客户端客户端用 flagsmith.setState(state) 恢复状态。Next.js App Router 示例// src/app/components/FeatureFlagProvider.tsx use client; import { ReactNode, useRef } from react; import { FlagsmithProvider } from flagsmith/flagsmith/react; import { IState } from flagsmith/flagsmith/types; import { createFlagsmithInstance } from flagsmith/flagsmith/isomorphic; export const FeatureFlagProvider ({ serverState, children, }: { serverState: IState; children: ReactNode; }) { const flagsmithInstance useRef(createFlagsmithInstance()); return ( FlagsmithProvider flagsmith{flagsmithInstance.current} serverState{serverState} {children}/ /FlagsmithProvider ); }; // src/app/layout.jsx import { ReactNode } from react; import { FeatureFlagProvider } from ./components/FeatureFlagProvider; import flagsmith from flagsmith/flagsmith/isomorphic; export default async function RootLayout({ children, }: Readonly{ children: ReactNode; }) { await flagsmith.init({ environmentID: YOUR_ENVIRONMENT_KEY, // Add optional identity, etc. }); const serverState flagsmith.getState(); return ( html langen head meta nameviewport contentinitial-scale1, widthdevice-width / /head body FeatureFlagProvider serverState{serverState} {children} /FeatureFlagProvider /body /html ); }Next.js Pages Router 示例// src/pages/_app.jsx import { FlagsmithProvider } from flagsmith/flagsmith/react; import { createFlagsmithInstance } from flagsmith/flagsmith/isomorphic; function MyApp({ Component, pageProps, flagsmithState }) { const flagsmithRef useRef(createFlagsmithInstance()); return ( FlagsmithProvider flagsmith{flagsmithRef.current} serverState{flagsmithState} Component {...pageProps} / /FlagsmithProvider ); } MyApp.getInitialProps async () { const flagsmithSSR createFlagsmithInstance(); await flagsmithSSR.init({ // fetches flags on the server environmentID: YOUR_ENVIRONMENT_KEY, identity: my_user_id, // optionally specify the identity of the user to get their specific flags }); return { flagsmithState: flagsmithSSR.getState() }; }; export default MyApp;客户端组件两种 Router 通用use client; // Only required by the app router version. import { useFlags } from flagsmith/flagsmith/react; export function MyComponent() { const flags useFlags([font_size], [example_trait]); // only causes re-render if specified flag values / traits change return ( div classNameApp font_size: {flags.font_size.value} example_trait: {flags.example_trait} /div ); }从服务端水合完成之后SDK 的用法与本文前面介绍的 React SDK 指南 完全一致。非 Next.js 的 SSR 场景如 Svelte同理服务端createFlagsmithInstance()按请求创建独立实例以防身份泄漏getState()传参给客户端客户端setState(state)恢复可选地再调用getFlags()强制刷新。多实例支持与 JSON Feature Values多实例import { createFlagsmithInstance } from flagsmith/flagsmith可创建相互独立的 SDK 实例适用于需要在应用内同时识别多个用户、并各自保留getValue/hasFeature能力的场景。JSON 远程配置调用flagsmith.getValue时指定json:true会自动把值解析为 JSON解析失败时回退到fallbackconst json flagsmith.getValue(json_value, { json: true, fallback: { foo: null, bar: null }, });TypeScript 类型安全Flagsmith 为 JavaScript 客户端提供完整的 TypeScript 支持并且可以通过泛型约束 feature 与 trait 名称防止拼写错误type FlagOptions font_size | hero; type TraitOptions example_trait;// 强制 flagsmith.getValue(flag:FlagOptions)、flagsmith.getTrait(trait:TraitOptions) import flagsmith from flagsmith/flagsmith; const typedFlagsmith flagsmith as IFlagsmithFlagOptions, TraitOptions; // useFlagsmith 同样支持泛型 const flagsmith useFlagsmithFlagOptions, TraitOptions(); // useFlags 会校验你传入的 key const flags useFlagsFlagOptions, TraitOptions([font_size], [example_trait]); // JSON 返回值也可被类型化 const json flagsmith.getValue{ foo: string | null; bar: string | null }(json_value, { json: true, fallback: { foo: null, bar: null }, }); console.log(json.foo); // typed as {foo: string|null, bar: string|null} // 未显式指定类型时getValue 从 fallback 推导此处为 number const font_size flagsmith.getValue(font_size, { fallback: 12 });常见问题如何在 init 的同时调用 identify、setTraits 等init在应用生命周期中应只调用一次建议在任何其他 flagsmith 调用之前执行init默认会拉取 flags若你紧接着就要识别用户可传入preventFetch: true关闭首次拉取避免重复请求。onChange 什么时候触发只要 flags 被获取就会触发onChange触发来源包括init、setTrait、incrementTrait、getFlags、identify、以及本地缓存中的 flags 评估。建议将onChange与你的状态管理配合使用例如触发重新评估hasFeature/getValue的 action。若不希望依赖 onChange上述函数都返回 Promise可等待新 flags 就绪后再取值await flagsmith.setTrait(age, 21); const hasFeature flagsmith.hasFeature(my_feature);onChange 回调会携带变更信息帮助你避免不必要的重渲染onChange(oldFlags, { isFromServer: true, // flags 来自服务端还是本地存储 flagsChanged: string[] | null, traitsChanged: string[] | null, }, loadingState)flags 缓存是如何工作的若cacheFlags为 trueSDK 会将 flag 评估结果缓存到本地异步存储。刷新浏览器后会立即以缓存 flags 触发一次 onChange其流程为调用init若cacheFlags启用检查本地存储中的 flags 与 traits若本地有缓存立即用缓存 flags 触发onChange同时拉取最新 flags再次触发onChange每次获取 flags 后更新本地缓存。默认情况下缓存永久保留如需清除可删除localStorage中的FLAGSMITH_DB_$ENVIRONMENT_ID键。为什么出现ReferenceError: XMLHttpRequest is not definedFlagsmith JavaScript 客户端使用fetchAPI 处理 REST 调用部分框架如 Manifest、Nuxt默认不支持。解决方式是向 SDK 提供自定义 fetch 实现详见 flagsmith-js-examples 中的 nuxt 插件示例。结合仓库源码理解 React SDK 的典型形态在 Flagsmith 前端仓库的代码片段生成器中可以找到与本文配套的官方集成模板init-react.js 与 init-react-native.js。它们展示了生产级项目的标准用法FlagsmithProvider只接收options{{ environmentID }}与flagsmith实例子组件通过useFlags([FEATURE_NAME])订阅关心的 feature并读取flags[FEATURE_NAME].enabled与.value。其中还体现了自托管场景的配置要点——当检测到自定义 Flagsmith URL 时会在初始化选项中自动注入api字段与上文的api初始化参数互相印证。React Native 模板则使用View/Text替换 Web 端的div/p其余结构完全一致佐证了 React 与 React Native 共享同一套 Hooks API 的设计。此外traits-react.js 等模板展示了 trait 读写与用户识别的完整代码可作为实战参考。赞分享后端前端【免费下载链接】flagsmithFlagsmith is an open-source feature flag platform with remote config, experimentation, and self-hosted or cloud deployment options.项目地址https://gitcode.com/gh_mirrors/fl/flagsmith点击查看免费下载相关推荐Flagsmith Flags API 深度指南SDK 读取 Feature Flags 与远程配置的核心接口解析Flagsmith Flags API 深度指南SDK 读取 Feature Flags 与远程配置的核心接口解析 Flagsmith 的 Flags API后端前端GrowthBook React SDK 源码级实战React 应用中的 Feature Flags、A/B 实验与 SSR 集成GrowthBook React SDK 源码级实战React 应用中的 Feature Flags、A/B 实验与 SSR 集成 本文基于 GrowthBo后端前端数据分析数据可视化Flagsmith Android/Kotlin SDK 集成指南从 Gradle 安装到 Flags、Traits 与实时更新Flagsmith Android/Kotlin SDK 集成指南从 Gradle 安装到 Flags、Traits 与实时更新 本文是 Flagsmith后端前端上一篇Yao Robot Executor 执行器架构解析Standard / DryRun / Sandbox 三种模式的设计与实战下一篇IPXWrapper终极指南在Windows 11上复活经典游戏联机功能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考