@ equinor/ 聚变框架- 模块- feature- flag
用于在应用程序中管理特征旗的Fusion框架模块. 提供基于插件的架构,用于定义、坚持和从多个来源,例如本地存储、 URL 查询参数或远程 API 中拖动特征标记.
特征
- 插件架构 ——将多旗源(本地存储,URL,API)编成一个提供商.
- 地方储存的持久性 ——被切换的旗帜活下来的页面通过重载
createLocalStoragePlugin。 。 。 . - URL 切换 - 通过查询参数启用或禁用旗帜
createUrlPlugin。 。 。 . - 远程 API - 从 HTTP 端点取出标记
createApiPlugin。 。 。 . - 可观察状态 ——通过RxJS可观测数据订阅国旗更改.
- 框架活动 - 发射
onFeatureFlagToggle(可撤销)和onFeatureFlagsToggled当事件模块存在时. - 类型值 - 旗帜可以携带通用的有效载荷(
IFeatureFlag<T>) (中文(简体) ).
安装
pnpm add @equinor/fusion-framework-module-feature-flag
使用量
注册模块
import { enableFeatureFlagging } from '@equinor/fusion-framework-module-feature-flag';
import {
createLocalStoragePlugin,
createUrlPlugin,
} from '@equinor/fusion-framework-module-feature-flag/plugins';
export const configure = (configurator) => {
enableFeatureFlagging(configurator, (builder) => {
// Persist toggled state in localStorage
builder.addPlugin(
createLocalStoragePlugin([
{ key: 'dark-mode', title: 'Dark mode' },
{ key: 'beta-search', title: 'Beta search', enabled: false },
]),
);
// Allow toggling via URL: ?beta-search=true
builder.addPlugin(createUrlPlugin(['beta-search']));
});
};
运行时读取旗帜
const featureFlags = modules.featureFlag;
// Check a single flag
if (featureFlags.getFeature('dark-mode')?.enabled) {
applyDarkTheme();
}
// Observe changes
featureFlags.features$.subscribe((features) => {
console.log('Current flags:', features);
});
程序切换旗帜
await featureFlags.toggleFeature({ key: 'dark-mode', enabled: true });
从 API 获取旗帜
import { createApiPlugin } from '@equinor/fusion-framework-module-feature-flag/plugins';
builder.addPlugin(
createApiPlugin({
httpClientName: 'my-api',
path: '/feature-flags',
}),
);
API 参考
主要出口@equinor/fusion-framework-module-feature-flag(中文(简体) )
| 导出 | 说明 |
|---|---|
enableFeatureFlagging | 在配置器上以可选的构建器调用方式注册模块. |
featureFlagModule 编号 : default | 人工登记模块描述符. |
FeatureFlagProvider | 管理旗下状态,调图,订阅. |
FeatureFlagConfigurator | 用于在配置时注册插件的构建器 . |
IFeatureFlag<T> | 界面描述一个单一特征旗. |
FeatureFlagPlugin | 用于提供并坚持标记的插件的接口 . |
插件导出( E)@equinor/fusion-framework-module-feature-flag/plugins(中文(简体) )
| 导出 | 说明 |
|---|---|
createLocalStoragePlugin | 永久旗帜国 localStorage (或 sessionStorage) (中文(简体) ). |
createUrlPlugin | 从导航的 URL 查询参数读取旗帜状态 . |
createApiPlugin | 从远程 HTTP 端点获取旗帜 . |
选择器导出( E)@equinor/fusion-framework-module-feature-flag/selectors(中文(简体) )
| 导出 | 说明 |
|---|---|
filterFeatures | RxJS 运算符,通过选择器函数过滤可观察到的特征映射. |
findFeature | RxJS 运算符,该运算符会发出一个匹配密钥或上游的单一旗帜. |
模拟出口(@equinor/fusion-framework-module-feature-flag/mock(中文(简体) )
| 导出 | 说明 |
|---|---|
enableFeatureFlagMock | 以内存注册模块 FeatureFlagMockConfigurator 而不是一个真正的插件. |
featureFlagMockModule | 人工登记模块描述符. |
FeatureFlagMockConfigurator | 使用构建器 addFeature编号 :setFeatures 用来在记忆中播种旗帜. |
操作遥测
IFeatureFlagProvider 扩展 TelemetryConnectable。供应商使用
telemetry.scope('feature-flag')较老的定制供应商的懒惰工厂倒闭;
关闭控点后取消一次切换并阻止
迟交报告。 切换摘要仍然针对本模块.
当主机登记遥测时,每个 toggleFeature编号 :toggleFeatures 呼叫报告
一个 fusion.feature-flag.toggle.duration 结果与 requested, (中文(简体) ), applied, (中文(简体) ),
rejected (未登记或只读)和 cancelled (否决权或被取代)
听者的工作)计数. 批量切换保留其现有的最新应用程序
行为; 被取代的收听者在调用结果导出前计数为已取消. 一个电话
其适用的旗帜全部被否决 cancelled; 仍在等待听众的切换
当模块被处理时 cancelled 有理无据 disposed。模块现在处理
它的提供者在主机被撕毁时,它也会释放插件连接. 读取诸如 hasFeature 为:
从未录入,且特性密钥和值从未导出 。 见 操作遥测。 。 。 .
测试
从 @equinor/fusion-framework-module-feature-flag/mock 切换到种子旗 localStorage 或 URL 。 真实的 FeatureFlagProvider,指向和订阅仍然运行着——只有旗帜源被替换.
import { enableFeatureFlagMock } from '@equinor/fusion-framework-module-feature-flag/mock';
enableFeatureFlagMock(configurator, (mock) => {
mock.addFeature({ key: 'my-flag', enabled: true });
});
默认
默认情况下不设旗帜 。 测试一下,没有种子会空出 features 对象,
匹配真实模块的零插件行为. setFeatures 种子若干旗帜和
addFeature 以密钥添加或替换一面旗帜 。 玩耍还是会经历现实
FeatureFlagProvider;模拟仅取代了初始旗源.
配置
模块通过配置 enableFeatureFlagging(configurator, callback)在你收到的回话中 IFeatureFlagConfigurator 采用下列方法的构建器:
| 方法 | 说明 |
|---|---|
addPlugin(handler) | 注册自定义插件厂. |
enableLocalFeatures(...args) | 快捷键 createLocalStoragePlugin (折旧)。 。 。 . |
enableUrlToggle(...args) | 快捷键 createUrlPlugin。 。 。 . |
插件生命周期
- 在配置期间,每个插件厂都通过
addPlugin。 。 。 . - 在模块初始化时,每个工厂都与
ConfigBuilderCallbackArgs。 。 。 . - 每个插件返回其
initial()旗帜和可选connect()钩. - 提供者合并所有初始旗帜并引用
connect()因此插件可以订阅切换事件(例如持续更改). - 配置器返回一个配置实例
- 模块创建提供者实例
- 提供者连接插件
- 提供者订阅切换动作并连接插件切换处理器
- 模块将特性标记模块返回到框架
export interface FeatureFlagPlugin {
/**
* connect the plugin to the provider
*/
connect: (args: { provider: IFeatureFlagProvider }) => VoidFunction | Subscription;
/**
* generate initial value for the provider
*/
initial?: () => ObservableInput<Array<IFeatureFlag>>;
}
本地存储
import { createLocalStoragePlugin } from '@equinor/fusion-framework-module-feature-flag/plugins';
允许存储特性旗被切换状态的插件
乌尔尔
import { createUrlPlugin } from '@equinor/fusion-framework-module-feature-flag/plugins';
拖曳特性的插件已丢弃url 搜索参数
自定义
初次
返回插件初始功能旗的async回调函数
连接
允许插件连接到特性旗提供者的 async callback
import {
enableFeatureFlagging,
type FeatureFlagPluginConfigCallback
} from '@equinor/fusion-framework-module-feature-flag';
const customPlugin: FeatureFlagPluginConfigCallback = async (args) => {
const myModule = await args.requireModule('my-module');
return {
initial: () => fetch('/api/features')
.then(res => res.json())
.then(features => features.map(feature => feature.source = 'my-source')),
connect: ({provider}) => {
/** subscribe to changes of feature flags */
provider.onFeatureToggle: async({flags}) => {
await fetch(
'/api/me/features',
{
method: 'PATCH',
body: flags.filter(feature => feature.source === 'my-source')
}
)
}
/** update feature flags */
signalR.received(data => {
provider.setFeatures(data.map(feature => feature.source = 'my-source'));
});
},
}
}
// ...configuration
enableFeatureFlagging(builder => {
builder.addPlugin(customPlugin);
})
选择器
过滤特性
过滤特定特性的运算符功能
import { filterFeatures } from '@equinor/fusion-framework-module-feature-flag/selectors';
const features$ = modules.featureFlag.feature$.pipe(
filterFeatures(x => x.enabled = true);
);
查找特性
选择特定特性的运算符
[大 除非值或选择器更改,否则操作员不会重放
import { findFeature } from '@equinor/fusion-framework-module-feature-flag/selectors';
const feature$ = modules.featureFlag.feature$.pipe('my-key');
活动
图片标签
切换特性前已发射事件
在 FeatureFlags 上切换
特性切换后发射的事件 (状态已更新)
使用量
// my-code.ts
const provider = modules.featureFlag;
const fooEnabled = provider.getFeatures('foo').enabled;
console.log('feature foo is ', fooEnabled ? 'enabled' : 'disabled');