尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Feature Flag Apple Store:基于 Global Config 与 Edge Middleware 的开关店实战指南

Feature Flag Apple Store:基于 Global Config 与 Edge Middleware 的开关店实战指南 Feature Flag Apple Store基于 Global Config 与 Edge Middleware 的开关店实战指南【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples本模板edge-middleware/feature-flag-apple-store演示了如何用 Vercel Global Config全局配置一种极低延迟的键值存储作为快速存储层通过 Edge Middleware 在请求入口处实时判断商店营业 / 打烊两种状态并借助 Global Config Dashboard 或 API Route 远程切换开关。读完本文你将掌握Global Config 的创建与连接串配置、Edge Middleware 中读取标志并改写路由的完整链路、以及通过 REST API 动态 upsert 标志值的写入方案可直接复用到任何灰度开关 / 紧急下架 / 维护页类场景。项目概览一个由标志位驱动的在线商店feature-flag-apple-store是一个 Next.jsPages Router示例页面本身是一个仿 Apple Store 的商品陈列页pages/index.tsx而真正有趣的是它外层包裹的一层开关逻辑标志为false营业时用户看到正常的商店页面标志为true打烊时用户在 Edge 层被静默改写rewrite到即将回归的提示页pages/_closed.tsx当GLOBAL_CONFIG环境变量缺失或连接串非法时请求被改写到一个环境变量配置引导弹窗页pages/missing-global-config.tsx。整个流程不经过任何应用服务器逻辑判断而是在边缘网络就近完成开关生效几乎是即时的。README 中声明其使用的框架为 Next.jsCSS 方案为 Tailwind涉及 Edge Functions、Edge Middleware 与 Global Config 三大能力并关联了 maintenance-page、ab-testing-simple 等同族模板。核心原理Edge Middleware 如何在请求入口拦截目录下的 middleware.ts 是整个开关逻辑的入口源码清晰地展现了三个关键步骤export const config { matcher: /, } export async function middleware(req: NextRequest) { // for demo purposes, warn when there is no GLOBAL_CONFIG if ( !process.env.GLOBAL_CONFIG || !parseConnectionString(process.env.GLOBAL_CONFIG) ) { req.nextUrl.pathname /missing-global-config return NextResponse.rewrite(req.nextUrl) } try { if (await get(storeClosed)) { req.nextUrl.pathname /_closed return NextResponse.rewrite(req.nextUrl) } } catch (error) { console.error(error) } }matcher 限定拦截范围matcher: /表示仅对首页请求触发中间件避免对静态资源、API 路由造成额外开销。配置缺失自愈先检查GLOBAL_CONFIG是否存在再用parseConnectionString校验其是否为合法的连接串不合法时直接 rewrite 到missing-global-config页面页面会引导用户补齐环境变量创建 Global Config → 拉取环境变量 → 重启/重新部署而不是让整个站点 500。标志读取与路由改写调用get(storeClosed)读取标志若为true则把/_closed改写为目标路径。NextResponse.rewrite是服务端内部改写URL 栏不变、体验无缝这也是维护页/开关页类方案的标准做法。异常兜底get包裹在try/catch中即使 Global Config 读取失败也只会打印错误并放行到正常页面fail-open保证业务可用性。标志的读写封装lib/feature-flags.ts 源码拆解所有标志操作集中在 lib/feature-flags.ts它同时封装了读供 Middleware 使用与写供 API Route 使用两条路径// We use prefixes to avoid mixing up the flags with other Global Config values const prefixKey (key: string) featureFlagsAppleStore_${key} export async function get(key: keyof FeatureFlags) { const prefixedKey prefixKey(key) const edgeConfig createClient(process.env.GLOBAL_CONFIG) const featureFlag await edgeConfig.getFeatureFlags(prefixedKey) return featureFlag }其中createClient与parseConnectionString均来自vercel/global-config包见 package.json 的 dependencies版本为^1.5.1。值得注意的实现细节键名前缀隔离所有标志统一加上featureFlagsAppleStore_前缀prefixKey注释明确说明这是为了避免与其他 Global Config 值混在一起。因此 README 要求你在 Global Config 中存放的键是featureFlagsAppleStore_storeClosed而代码里访问的却是storeClosed——前缀在prefixKey内部拼接二者一一对应。类型安全FeatureFlags接口声明了storeClosed: booleanget/set的入参被限制为keyof FeatureFlags从编译期防止拼错键名。通过 API Route 动态开店 / 关店README 提供了两个内置的管理端点这也是模板区别于只读开关的亮点运行时写回标志值。源码位于 pages/api/store/open.ts 与 pages/api/store/close.tsexport const config { runtime: edge, }两个路由都声明为runtime: edgeEdge Runtime并分别调用set(storeClosed, false)开店与set(storeClosed, true)关店。成功后返回 JSON{ status: ok, message: Store is now open/closed }失败则返回{ status: error, message }。写入路径的核心在feature-flags.ts的set函数const connectionString parseConnectionString(process.env.GLOBAL_CONFIG!) const globalConfigId connectionString.id const response await fetch( https://api.vercel.com/v1/global-config/${globalConfigId}/items?teamId${process.env.TEAM_ID_VERCEL}, { method: PATCH, headers: { Authorization: Bearer ${process.env.AUTH_BEARER_TOKEN}, content-type: application/json, }, body: JSON.stringify({ items: [{ operation: upsert, key: prefixedKey, value }], }), } ) return response.status 200从源码可以梳理出写入所需的完整要素通过parseConnectionString从连接串中解析出 Global Config 的id调用 Vercel REST APIPATCH /v1/global-config/{id}/itemsteamId取自TEAM_ID_VERCEL环境变量认证头使用Authorization: Bearer ${AUTH_BEARER_TOKEN}请求体为items数组operation: upsert表示键存在则更新、不存在则创建以 HTTP 状态码是否为200判定成功。因此README 特别提醒若要使用open/close两个端点必须在.env.local中自行提供TEAM_ID_VERCEL与AUTH_BEARER_TOKEN。而set内部也做了双保险校验——缺少AUTH_BEARER_TOKEN或GLOBAL_CONFIG时直接抛出明确的错误信息。从零开始安装与配置 Global Config方式一一键部署VercelREADME 提供了 Vercel 的一键部署入口部署参数中已内嵌了创建 Global Config 的初始化数据GLOBAL_CONFIG环境变量会被创建并在其中预置featureFlagsAppleStore_storeClosed: true即初始状态为关店。部署完成后即可直接访问线上地址体验开关效果。方式二克隆到本地开发使用 pnpm 与 create-next-app 引导模板pnpm create next-app --example https://github.com/vercel/examples/tree/main/edge-middleware/feature-flag-apple-store接着按 README 指引复制环境变量文件cp .env.example .env.localGLOBAL_CONFIG是模板必需的运行环境变量你需要在 Vercel 控制台创建一个 Global ConfigGlobal Config即分布式键值存储读取延迟极低适合边缘场景将其连接串connection string绑定到项目的GLOBAL_CONFIG环境变量向该 Global Config 中写入如下内容{ featureFlagsAppleStore_storeClosed: true }然后启动开发服务器pnpm dev若GLOBAL_CONFIG未配置或连接串非法访问首页会被 rewrite 到missing-global-config页面pages/missing-global-config.tsx页面会以弹窗形式列出三步修复指引配置正确后刷新即可看到正常商店页。需要说明的是本地开发时还应通过vercel env pull一类方式同步线上环境变量确保.env.local中的值完整详见弹窗页给出的步骤。注.env.example仅定义了模板所需变量名结合源码可知运行态必需GLOBAL_CONFIG启用 API 开关端点时还需TEAM_ID_VERCEL与AUTH_BEARER_TOKEN。营业状态切换的两种操作方式方式一Global Config Dashboard直接登录 Vercel 控制台打开该项目的 Global Config 管理界面将featureFlagsAppleStore_storeClosed的值在true/false之间切换即可——无需重新部署、无需发版下一次请求在边缘层就会命中新状态。方式二内置 API 路由本地开发时需已配置TEAM_ID_VERCEL与AUTH_BEARER_TOKEN通过浏览器或 curl 访问# 开店将 storeClosed 置为 false http://localhost:3000/api/store/open # 关店将 storeClosed 置为 true http://localhost:3000/api/store/close两个端点最终都会调用set()走 Vercel REST API 完成upsert返回 JSON 结果。生产环境同样可以部署后通过线上 URL 调用实现一键打烊式的运营操作。关键文件速查文件仓库根目录相对路径职责middleware.tsEdge 拦截入口校验配置、读取标志、改写路由lib/feature-flags.ts标志读/写封装前缀键、vercel/global-config客户端、REST API upsertpages/api/store/open.ts开店端点storeClosed falsepages/api/store/close.ts关店端点storeClosed truepages/_closed.tsx打烊提示页被 rewrite 的目标pages/missing-global-config.tsx配置缺失引导弹窗页pages/index.tsx正常营业时的商店主页components/nav.tsx顶部导航栏next.config.js配置next/image允许加载store.storeimages.cdn-apple.com域名图片package.json依赖与脚本dev/build/start/lint总结与扩展思路这个模板把功能开关的完整闭环浓缩到了不到 200 行代码Edge Middleware 负责零延迟读取与路由改写vercel/global-config负责极低延迟存储API Route 负责运行时写入。其核心设计模式——前缀隔离键名 fail-open 异常兜底 边缘层 rewrite——可以平滑迁移到更多场景灰度发布按比例或按用户分桶读取标志rewrite 到新旧版本页面紧急维护将storeClosed换成maintenanceMode配合 maintenance-page 模板使用A/B 实验结合 ab-testing-simple 的思路在同一边缘层分发不同实验组。本仓库其余同族示例如 edge-middleware 目录 下的 feature-flag-* 系列分别演示了不同标志服务提供商的接入方式可与本模板对照学习。【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表