关于 flags-sdk
flags-sdk 是面向 Next.js 和 SvelteKit 的功能标志工具包及配套技能,允许将标志声明为可调用函数,并通过适配器连接不同提供方。其服务端评估与预计算模式用于避免布局偏移并保留静态页面。
主要功能
- 01将功能标志声明为函数
- 02通过适配器连接标志提供方
- 03在服务端评估标志
- 04使用预计算提供静态变体
- 05支持 Next.js 和 SvelteKit
适用场景
- 01在 Next.js 应用中添加功能标志
- 02在 SvelteKit 项目中评估标志
- 03使用不同提供方配置标志适配器
- 04预计算页面变体以保留静态页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ vercel/ flags --skill flags-sdk安装后在 Claude Code 中输入/flags-sdk确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api.mdnextjs.mdproviders.mdsveltekit.md详细介绍
设置和使用 Flags SDK
Flags SDK(flags npm 软件包)是面向 Next.js 和 SvelteKit 的功能标记工具包。它会将每个功能标记转换为可调用的函数,通过适配器支持任意标记提供方,并使用预计算模式保持页面静态。Vercel Flags 是官方提供方,其适配器为 @flags-sdk/vercel。
本技能涵盖代码操作。规划功能标记、在 Flags SDK、@vercel/flags-core 和 OpenFeature 之间进行选择,以及在控制面板或通过 vercel flags CLI 管理标记,都属于 vercel-flags 技能。归档标记、删除标记或移除变体时,必须遵循该技能中的检查步骤(先移除代码,确认 Skew Protection 窗口内没有评估记录,再归档,然后执行 rm);没有该技能时,不要运行这些命令。如果无法使用该技能,请建议运行 npx skills add vercel/flags@vercel-flags(不要自动安装),同时运行 vercel flags <cmd> --help。对于使用其他框架的项目,请使用 @vercel/flags-core 替代此 SDK(Core SDK)。
用户要求安装、配置或设置 SDK 时,请遵循设置 SDK(如果缺少 .env.local,还要执行 vercel env pull)。用户要求在代码中添加标记时,请遵循创建标记或添加 Vercel 上已有的标记。在应用仓库中遇到含糊的请求时,应按完整流程处理。不要把 CLI 操作留作用户的“后续步骤”;请自行执行。
核心概念
将标记作为代码
每个标记都声明为函数。在调用位置无需使用字符串键:
import { flag } from 'flags/next';
export const exampleFlag = flag({
key: 'example-flag',
decide() { return false; },
});
const value = await exampleFlag();
服务端评估
标记在服务端评估,以避免布局偏移、保持页面静态并确保机密性。将路由中间件与预计算模式结合,从 CDN 提供静态变体。
适配器模式
适配器会替换标记声明中的 decide 和 origin,将标记连接到提供方。Vercel Flags(@flags-sdk/vercel)是官方适配器。Statsig、LaunchDarkly、PostHog 等也提供第三方适配器。
import { flag } from 'flags/next';
import { vercelAdapter } from '@flags-sdk/vercel';
export const exampleFlag = flag({
key: 'example-flag',
adapter: vercelAdapter,
});
版本说明:SDK 以
flags发布(从@vercel/flags更名而来;旧名称仍会出现在变更日志中)。flags4.2.0+ 支持通过引用传入适配器工厂(adapter: vercelAdapter),并会在每个声明中解析一次。旧版本要求调用工厂(adapter: vercelAdapter())。新版本仍支持调用形式,因此除非目标版本为flags< 4.2.0,否则优先使用简写形式。
设置 SDK
一次性项目设置。当尚未安装 Flags SDK,或缺少 Toolbar、Flags Explorer 或 .env.local 时,请执行此操作。已完成的步骤可跳过。
开始之前
检查项目状态,以调整命令并确定哪些步骤可以跳过:
- 存在哪个锁文件(
pnpm-lock.yaml、package-lock.json、yarn.lock、bun.lockb)?→ 相应调整所有软件包管理器命令(pnpm add、npm install、yarn add、bun add)。 package.json中是否有flags?→ 跳过安装(步骤 1)- 项目是否已关联?→ 跳过步骤 2 中的
vercel link .env.local是否包含VERCEL_OIDC_TOKEN=(或 SDK 密钥FLAGS=)?→ 环境变量已拉取,跳过步骤 3package.json中是否有@vercel/toolbar?→ 跳过 Toolbar 设置(步骤 4)- 是否存在
flags.ts(或lib/flags.ts、src/flags.ts)?→ 跳过创建(步骤 5) - 是否存在
app/.well-known/vercel/flags/route.ts?→ Flags Explorer 已设置,跳过步骤 6
步骤
-
安装软件包(如果尚未添加到
package.json):pnpm i flags @flags-sdk/vercel -
将项目关联到 Vercel(
vercel env pull和本地 OIDC 令牌刷新所必需):前提条件:必须已安装并完成身份验证的 Vercel CLI。如果尚未安装,请运行
pnpm i -g vercel。如果遇到身份验证或关联问题,请使用已安装的vercel-cliskill。如果尚未安装,请建议用户使用npx skills add vercel/vercel@vercel-cli安装(不要自动安装),同时暂时依靠vercel <command> --help。使用
vercel project inspect --non-interactive验证关联,并检查报告的所有者和项目名称;仅有.vercel/目录并不能证明项目已关联。如果报告显示link_required,请运行vercel link。如果用户指定了项目或团队,而输出与之不同,请停止操作并询问用户,不要重新关联。 -
拉取环境变量:如果
.env.local中缺少VERCEL_OIDC_TOKEN=,请按照拉取环境变量中的说明操作。 -
设置 Vercel Toolbar(如果尚未配置):
- 运行
pnpm i @vercel/toolbar - 使用 Toolbar 插件包装
next.config.ts - 在根布局中渲染
<VercelToolbar />完整代码请参阅 references/nextjs.md — Toolbar 设置。
- 运行
-
确保存在
flags.ts:如果文件不存在,请创建flags.ts(或与项目结构匹配的lib/flags.ts/src/flags.ts),并写入export {},以便 TypeScript 将其视为模块。Flags Explorer 会导入此文件 — 请在发现路由之前创建它。 -
设置 Flags Explorer(如果尚未配置):创建
app/.well-known/vercel/flags/route.ts— 参阅 Flags Explorer 设置。仅在flags.ts存在后执行此操作。将导入指向实际的 flags 文件路径(代码片段假定文件位于根目录flags.ts)。
拉取环境变量
vercel env pull 会将 Development 凭据写入 .env.local:vercelAdapter 在本地使用的 Vercel OIDC 令牌(部署会自动获取该令牌,入门指南)以及供 Flags Explorer 和覆盖项使用的 Development FLAGS_SECRET。在以下情况下运行此命令:
.env.local中缺少VERCEL_OIDC_TOKEN=(或 SDK 密钥FLAGS=)- 你创建了项目的首个 flag;启用 Vercel Flags 会为每个环境创建一个
FLAGS_SECRET - 本地评估因身份验证错误而失败;SDK 会通过已关联的项目刷新过期令牌,重新拉取是备用方案
SDK 密钥(FLAGS)仅适用于 Vercel 之外的应用、自定义环境或其他项目的 flags(SDK 密钥)。如果拉取后仍缺少 FLAGS_SECRET,请按照 FLAGS_SECRET 中的说明生成。
创建 flag
当用户要求创建或添加一个尚未在 Vercel 上创建的功能 flag 时,请按顺序执行以下步骤。如果该 flag 已在控制面板中创建(提示词中有说明,或 vercel flags create 报告该键已存在),请改为按照添加已在 Vercel 上存在的 flag中的说明操作。
开始之前
- 如果缺少软件包、Vercel 关联、
.env.local、Toolbar、flags.ts或 Flags Explorer,请先完成设置 SDK。跳过已完成的步骤。 .env.local中是否包含VERCEL_OIDC_TOKEN=?→ 环境变量已拉取;如果本地评估因身份验证错误而失败,请参阅拉取环境变量。- 是否存在
flags.ts(或lib/flags.ts、src/flags.ts)?→ 请在该文件中添加,而不是从头创建。
步骤
-
确保已设置 SDK:如有需要,请按照设置 SDK 操作,然后继续。
-
在 Vercel 中注册标志:针对已关联的项目运行
vercel flags create <flag-key> --kind boolean --description "<description>",或者传入--project <name-or-id>和--scope <team>。选择与标志类型参数匹配的 kind;之后无法更改。 -
拉取环境变量:如果这是项目的第一个标志,请再次按照拉取环境变量操作;激活时已创建
FLAGS_SECRET。 -
在代码中声明标志:使用
vercelAdapter将其添加到flags.ts(如果文件不存在,则创建该文件):import { flag } from 'flags/next'; import { vercelAdapter } from '@flags-sdk/vercel'; export const myFlag = flag({ key: 'my-flag', adapter: vercelAdapter, }); -
使用标志:在页面或组件中调用它,并根据结果有条件地渲染内容:
import { myFlag } from '../flags'; export default async function Page() { const enabled = await myFlag(); return <div>{enabled ? 'Feature on' : 'Feature off'}</div>; }
添加 Vercel 中已存在的标志
如果标志是在控制面板中创建的,或由其他人创建,请使用此流程;例如,提示词说标志“已创建”,或要求你运行 vercel flags inspect 时。对于已存在的键,不要运行 vercel flags create。
- 确保已设置 SDK:如有需要,请按照设置 SDK操作。
- 读取定义:运行
vercel flags inspect <flag-key>。记下 kind、变体(值和标签)、描述,以及各环境提供的内容。 - 拉取环境变量:如果
.env.local中没有VERCEL_OIDC_TOKEN=,请按照拉取环境变量操作。 - 声明标志:使用
vercelAdapter将其添加到flags.ts。映射inspect的输出:key:照原样使用打印出的标志键- kind → 类型参数:
boolean→flag<boolean>,string→flag<string>,number→flag<number>,json→flag<YourType> description:从inspect输出中复制defaultValue:标志已归档或评估失败时提供的值(通常是生产环境当前提供的值)options:可选;使用预计算时,或希望在 Flags Explorer 中列出变体时,使用与变体相同的配置identify:如果标志有定向规则,则添加或复用一个,并使用控制面板中配置的实体属性(参见带评估上下文的标志)
export const welcomeMessage = flag<string>({ key: 'welcome-message', description: 'Copy shown on the landing page', defaultValue: 'control', adapter: vercelAdapter, }); - 使用标志:按照创建标志的第 5 步操作。
Vercel Flags 适配器
@flags-sdk/vercel 将 flag() 声明连接到 Vercel Flags。vercelAdapter 使用项目的 Vercel OIDC 令牌进行身份验证,并评估当前环境的配置;SDK 密钥(FLAGS)仅用于手动身份验证:适用于 Vercel 之外的应用、自定义环境或其他项目的标志(SDK 密钥)。激活 Vercel Flags 时,会为每个环境创建一个 FLAGS_SECRET,供 Flags Explorer 使用。
有关用户定向、属性类型、自定义适配器配置、共享 @vercel/flags-core 客户端以及 Flags Explorer 端点的信息,请参阅references/providers.md — Vercel。
更改标志提供的内容(启用、设置、拆分、逐步推出、规则、归档)应在控制面板中或使用 vercel flags 完成,而不是在代码中进行。vercel-flags 技能涵盖这些流程;vercel flags <cmd> --help 会列出可用选项。
声明标志
使用 Vercel Flags 时,请按照创建标志中的示例,使用 vercelAdapter 声明标志。其他提供方请参阅references/providers.md。以下是通用的 flag() 模式。
基本标志
import { flag } from 'flags/next'; // or 'flags/sveltekit'
export const showBanner = flag<boolean>({
key: 'show-banner',
description: 'Show promotional banner',
defaultValue: false,
options: [
{ value: false, label: 'Hide' },
{ value: true, label: 'Show' },
],
decide() { return false; },
});
携带评估上下文的 Flag
使用 identify 确定请求的对象。返回的实体会传递给 decide:
import { dedupe, flag } from 'flags/next';
import type { ReadonlyRequestCookies } from 'flags';
interface Entities {
user?: { id: string };
}
const identify = dedupe(
({ cookies }: { cookies: ReadonlyRequestCookies }): Entities => {
const userId = cookies.get('user-id')?.value;
return { user: userId ? { id: userId } : undefined };
},
);
export const dashboardFlag = flag<boolean, Entities>({
key: 'new-dashboard',
identify,
decide({ entities }) {
if (!entities?.user) return false;
return ['user1', 'user2'].includes(entities.user.id);
},
});
使用 vercelAdapter 时,返回对象中的实体和属性名称(此处为 user.id)是仪表板规则和 vercel flags split|rollout|rules --by 的目标。它们必须与仪表板中配置的实体及属性类型相匹配。请参阅 references/providers.md — 用户定向 和 属性类型。
使用其他 Adapter 的 Flag
Adapter 将 Flag 连接到第三方提供商。每个 Adapter 都会替换 decide 和 origin:
import { flag } from 'flags/next';
import { statsigAdapter } from '@flags-sdk/statsig';
export const myGate = flag({
key: 'my_gate',
adapter: statsigAdapter.featureGate((gate) => gate.value),
identify,
});
请参阅 references/providers.md,了解所有受支持的 Adapter。
关键参数
| 参数 | 类型 | 描述 |
|---|---|---|
key | string | 唯一的 Flag 标识符 |
decide | function | 解析 Flag 的值 |
defaultValue | any | 如果 decide 返回 undefined 或抛出异常,则使用此回退值 |
description | string | 在 Flags Explorer 中显示 |
origin | string | 用于在提供商仪表板中管理 Flag 的 URL |
options | { label?: string, value: any }[] | 可能的值,用于预计算和 Flags Explorer |
adapter | Adapter | 实现 decide 和 origin 的提供商 Adapter |
identify | function | 返回供 decide 使用的评估上下文(实体) |
去重
将共享函数(尤其是 identify)包装在 dedupe 中,使其每个请求只运行一次:
import { dedupe } from 'flags/next';
const identify = dedupe(({ cookies }) => {
return { user: { id: cookies.get('uid')?.value } };
});
注意:Pages Router 中无法使用 dedupe。
批量评估
若要一次评估多个 Flag,请调用 evaluate()(来自 flags/next),而不是逐个等待 Flag 或使用 Promise.all()。若要评估单个 Flag,直接调用即可:await myFlag()。
import { evaluate } from 'flags/next';
import { flagA, flagB } from '../flags';
// avoid: each await blocks the next, so the flags resolve sequentially
const a = await flagA();
const b = await flagB();
// avoid: parallel, but each flag is evaluated in isolation
const [a, b] = await Promise.all([flagA(), flagB()]);
// prefer: shares work across the batch
const [a, b] = await evaluate([flagA, flagB]);
evaluate() 比这两种方式都快。逐个等待 Flag 会让总延迟等于所有 Flag 的评估时间之和,而不是最慢的单个 Flag 的评估时间;Promise.all() 虽然会并行运行,但会分别评估每个 Flag。evaluate() 会为整个批次只预先读取一次 headers、cookies 和 overrides,并让 Adapter 在单次调用中解析一组 Flag,从而减少运行时需要管理的并行 Promise 数量,也降低异步工作被其他微任务中断的可能性。
它接受数组(按位置返回结果)或对象(按键返回结果):
const [a, b] = await evaluate([flagA, flagB]);
const { a, b } = await evaluate({ a: flagA, b: flagB });
在 App Router 之外(Pages Router 的 getServerSideProps/API 路由,或路由中间件),将请求作为第二个参数传入:await evaluate([flagA, flagB], request)。
evaluate() 始终在请求时评估 Flag。它不用于读取预计算(静态)值——读取这类值时,请使用 getPrecomputed(或使用代码调用 Flag:await myFlag(code, flagGroup))。
Adapter 可以选择通过实现可选的 bulkDecide 钩子来支持批处理。Vercel Adapter(@flags-sdk/vercel)实现了该钩子——解析数百个 Flag 时,评估时间大约可减少 10 倍。有关如何实现 bulkDecide,请参阅 references/providers.md — 自定义 Adapter;完整签名请参阅 references/api.md — evaluate。
Flags Explorer 设置
Next.js(App Router)
// app/.well-known/vercel/flags/route.ts
import { createFlagsDiscoveryEndpoint } from 'flags/next';
import { getProviderData } from '@flags-sdk/vercel';
import * as flags from '../../../../flags'; // adjust if flags live under lib/ or src/
export const GET = createFlagsDiscoveryEndpoint(async () => {
return getProviderData(flags);
});
使用外部提供商的数据
将第三方提供商与 Vercel Flags 配合使用时,请使用 mergeProviderData 合并其数据。每个提供商适配器都会导出自己的 getProviderData——请参阅 references/providers.md 中针对各提供商的示例。
SvelteKit
// src/hooks.server.ts
import { createHandle } from 'flags/sveltekit';
import { FLAGS_SECRET } from '$env/static/private';
import * as flags from '$lib/flags';
export const handle = createHandle({ secret: FLAGS_SECRET, flags });
FLAGS_SECRET
预计算和 Flags Explorer 必需。Vercel Flags 激活后会为每个环境创建一个值。请保留现有值;在常规 SDK 设置期间不要轮换这些值。本地值缺失不代表远程值缺失:请先检查目标环境,然后按照 拉取环境变量 中的说明配置 Development。
仅在某个环境缺少密钥时才生成。使用 32 个经加密学安全随机生成的字节,并进行 base64 编码;每个环境使用不同的值。将 Preview 和 Production 的值标记为 Sensitive。请将生成的值直接发送到存储位置,例如通过 stdin 传递给 vercel env add;不要将其打印到终端输出、日志或聊天中,也不要将其嵌入命令参数。
预计算模式
使用预计算可在使用功能标志的同时保持页面为静态页面。中间件会评估标志,并通过重写将结果编码到 URL 中。页面读取预计算的值,而不重新评估。
高级流程:
- 声明标志并将其分组到数组中
- 在中间件中调用
precompute(flagGroup),获取code字符串 - 将请求重写为
/${code}/original-path - 页面从
code中读取标志值:await myFlag(code, flagGroup)
有关完整实现详情,请参阅特定框架的参考文档:
- Next.js:请参阅 references/nextjs.md——涵盖代理中间件、预计算设置、ISR、generatePermutations 和多个分组
- SvelteKit:请参阅 references/sveltekit.md——涵盖 reroute 钩子、中间件、预计算设置、ISR 和预渲染
自定义适配器
创建一个适配器工厂,返回包含 origin 和 decide 的对象。有关完整模式(包括默认适配器和单例客户端示例),请参阅 references/providers.md。
加密函数
若要在浏览器中保护标志数据的机密性(Flags Explorer 使用),可使用以下函数:
| 函数 | 用途 |
|---|---|
encryptFlagValues | 加密已解析的标志值 |
decryptFlagValues | 解密标志值 |
encryptFlagDefinitions | 加密标志定义/元数据 |
decryptFlagDefinitions | 解密标志定义 |
encryptOverrides | 加密工具栏覆盖值 |
decryptOverrides | 解密工具栏覆盖值 |
默认情况下,所有函数都会使用 FLAGS_SECRET。示例:
import { encryptFlagValues } from 'flags';
import { FlagValues } from 'flags/react';
async function ConfidentialFlags({ values }) {
const encrypted = await encryptFlagValues(values);
return <FlagValues values={encrypted} />;
}
React 组件
import { FlagValues, FlagDefinitions } from 'flags/react';
// Renders script tag with flag values for Flags Explorer
<FlagValues values={{ myFlag: true }} />
// Renders script tag with flag definitions for Flags Explorer
<FlagDefinitions definitions={{ myFlag: { options: [...], description: '...' } }} />
参考文档
框架和提供商的详细指南分开存放,以精简上下文:
- references/nextjs.md:Next.js 快速入门、工具栏、App Router、Pages Router、中间件/代理、预计算、去重、仪表板页面、营销页面、Suspense 回退
- references/sveltekit.md:SvelteKit 快速入门、工具栏、钩子设置、通过 reroute + 中间件进行预计算、仪表板页面、营销页面
- references/providers.md:所有提供商适配器——Vercel、Global Config、Statsig、LaunchDarkly、PostHog、GrowthBook、Flagsmith、Reflag、Split、Optimizely、OpenFeature 和自定义适配器
- references/api.md:
flags、flags/react、flags/next和flags/sveltekit的完整 API 参考