Компонент, директива и composables
Опции инициализации
ts
app.use(FeatureToggles, {
// Статические значения флагов (boolean или строка варианта)
flags: { newDashboard: true, checkoutFlow: 'v2' },
// Асинхронный загрузчик — получает флаги с бэкенда
loader: async () => {
const res = await fetch('/api/feature-flags')
return res.json()
},
// Интервал поллинга для загрузчика в мс (по умолчанию: 0 = отключено)
reloadInterval: 60_000,
// Разрешить ?feature:flagName=true в URL (по умолчанию: true в dev, false в prod)
urlOverrides: true,
// Префикс URL-параметра (по умолчанию: 'feature')
urlPrefix: 'feature',
// Значение, возвращаемое для неизвестных флагов (по умолчанию: false)
defaultValue: false,
// Переменные, привязанные к флагу
variables: {
newCheckout: { maxItems: 5, theme: 'dark' },
},
// Именованные группы флагов
groups: {
beta: ['betaSearch', 'newDashboard'],
maintenance: ['maintenanceMode', 'readOnlyBanner'],
},
// Обеспечение зависимостей: если требуемый флаг выключен, зависимый тоже принудительно выключается
dependencies: {
aiSuggestions: ['newSearch'],
},
// Контекстные правила — вычисляются реактивно, приоритет ниже setFlag/URL
rules: {
darkMode: () => window.matchMedia('(prefers-color-scheme: dark)').matches,
},
// Метаданные флагов для DevTools и CLI
meta: {
newDashboard: {
description: 'New UI',
owner: 'alice',
addedAt: '2025-03-01',
ticket: 'PROJ-42',
},
},
// Даты автоматического истечения — после этой даты флаг считается истёкшим
expiry: {
christmasBanner: '2025-01-10',
},
// Живые обновления с сервера (SSE или WebSocket)
liveUpdates: {
type: 'sse',
url: '/api/flags/stream',
},
// Серверный снимок флагов для предотвращения расхождения при гидратации
ssrState: window.__FEATURE_FLAGS__,
})Компонент <Feature>
vue
<!-- Базовый -->
<Feature name="newDashboard">
<NewDashboard />
</Feature>
<!-- Слот fallback -->
<Feature name="betaSearch">
<template #default><BetaSearchBar /></template>
<template #fallback><LegacySearchBar /></template>
</Feature>
<!-- Проп fallback -->
<Feature name="betaSearch" fallback="Feature is under development">
<BetaSearchBar />
</Feature>
<!-- Инвертированный — показывать, когда флаг выключен -->
<Feature name="maintenanceMode" :inverted="true">
<MainContent />
</Feature>
<!-- Обернуть в HTML-элемент -->
<Feature name="newDashboard" tag="section">
<NewDashboard />
</Feature>
<!-- Состояние загрузки, пока работает загрузчик -->
<Feature name="loaderFlag">
<template #loading><Spinner /></template>
<template #default><NewFeature /></template>
<template #fallback><OldFeature /></template>
</Feature>
<!-- Группа — показывать, когда ВСЕ флаги в группе включены -->
<Feature group="beta">
<BetaLabel />
</Feature>Пропы
| Проп | Тип | По умолчанию | Описание |
|---|---|---|---|
name | string | — | Имя флага |
group | string | — | Имя группы (альтернатива name) |
fallback | string | Component | null | Что рендерить, когда флаг выключен |
inverted | boolean | false | Рендерить, когда флаг равен false |
tag | string | — | Обернуть содержимое в HTML-элемент (по умолчанию без обёртки) |
Слоты
| Слот | Описание |
|---|---|
default | Содержимое, когда флаг включён |
fallback | Содержимое, когда флаг выключен |
loading | Содержимое, пока флаги загружаются через loader |
Директива v-feature
vue
<!-- Показывать, когда флаг включён -->
<div v-feature="'newDashboard'">...</div>
<!-- Показывать, когда флаг выключен (инвертировано) -->
<div v-feature:not="'betaSearch'">...</div>
<!-- Показывать, когда ВСЕ флаги включены -->
<div v-feature="['newDashboard', 'betaSearch']">...</div>Работает как v-show (переключает display: none) — узел DOM всегда присутствует. Для поведения в стиле v-if используйте <Feature>.
useFeature
ts
import { useFeature } from 'vue-feature-toggles'
// Один флаг → Ref<boolean>
const isNewDashboard = useFeature('newDashboard')
// Несколько флагов → Record<string, Ref<boolean>>
const { newDashboard, betaSearch } = useFeature(['newDashboard', 'betaSearch'])
// Проверка AND по нескольким флагам → Ref<boolean>
const allEnabled = useFeature('newDashboard', 'betaSearch')Мультивариантные флаги и <FeatureVariant>
Флаги могут содержать строковый вариант вместо boolean — полезно для A/B-тестов и многоэтапных раскаток.
ts
app.use(FeatureToggles, {
flags: { checkoutFlow: 'v2' },
})ts
import { useFeatureVariant } from 'vue-feature-toggles'
const variant = useFeatureVariant('checkoutFlow') // Ref<string>vue
<FeatureVariant name="checkoutFlow">
<template #v1><CheckoutV1 /></template>
<template #v2><CheckoutV2 /></template>
<template #fallback><CheckoutLegacy /></template>
</FeatureVariant>URL-переопределения работают идентично: ?feature:checkoutFlow=v2.