使用 Next.js 和 App Router 实现功能开关

2025-06-09

使用 Next.js 和 App Router 实现功能开关

介绍

在本文中,我们将讨论如何结合 Vercel 和功能开关(Flagsmith - 开源)的强大功能,使用 Next.Js 功能开关在不到 15 分钟的时间内从头构建和部署一个配置控制的应用程序。本文由Abhishek Agarawal 🚀 撰写!

通过本博客,我们将了解:

  • 功能标志的重要性
  • 如何使用 Vercel Approuter 创建基本的 Next.js 应用程序
  • 设置 Vercel 并将项目推送到 Vercel
  • 部署应用程序
  • 添加功能标志
  • 当我们从 Flagsmith 控制台更新功能标志时,请在网站上查看实时变化

背景

Vercel 是开发人员最喜爱的开发、预览和发布应用程序的平台。它使构建复杂的应用程序变得更容易、更高效。

Next.js 是由 Vercel 提供的一个流行的开源框架,它基于 Node.js 构建,用于构建服务器端渲染 (SSR) React 应用程序。它的核心优势包括更快的页面加载速度、更佳的 SEO 以及更佳的开发者体验。

功能开关提供了开箱即用的生产环境功能管理功能。我们选择与 Flagsmith ( https://github.com/Flagsmith/flagsmith ) 集成。设置和集成过程无缝衔接,只需点击几个按钮即可获得强大的功能。

理解功能标记及其重要性

功能标记(也称为功能切换或功能翻转)是一种强大的软件开发技术,它使开发人员能够以可控且循序渐进的方式将新功能和变更部署到生产环境中。功能标记并非一次性发布所有变更,而是允许您针对不同用户群选择性地启用或禁用特定功能。

但为什么这种方法如此有价值呢?功能标记已成为现代软件开发的重要组成部分,原因如下:

  1. 降低部署风险:功能标记功能可降低部署新功能的风险。通过逐步将变更推送至一小部分用户,开发者可以在将新功能推广至更广泛的受众之前,密切监控其影响和性能。这有助于及早发现潜在问题,并在必要时进行快速调整。
  2. 持续交付和实验:借助功能标记功能,您可以持续交付更新并实验新功能,而不会对整个用户群造成干扰。这不仅支持敏捷开发实践,还鼓励实验文化,让开发人员能够测试假设并收集真实数据,为决策提供参考。
  3. 个性化用户体验:通过根据各种特征(例如职业、位置、订阅类型)对用户进行细分,您可以为不同的用户群体提供量身定制的个性化体验。这让您能够提供有针对性的内容,对不同的版本进行 A/B 测试,并优化用户参与度。
  4. 热修复和回滚:功能开关为快速热修复和回滚提供了安全保障。如果某个新功能导致意外问题或收到负面反馈,您可以轻松使用开关将其关闭,从而避免完全重新部署。

将 Flagsmith 与 Next.js 集成

在本指南中,我们选择 Flagsmith 作为功能标记解决方案。Flagsmith 是一个开源平台,提供用户友好的界面,用于管理功能标记A/B 测试细分覆盖。您无需修改​​代码即可控制功能行为,使其成为管理具有多种功能变体的复杂项目的强大工具。

通过将 Flagsmith 集成到我们在 Vercel 上部署的 Next.js 项目中,我们能够分阶段推出、根据用户细分控制功能可见性,并实时动态更改功能设置,而无需重新部署应用程序。

让我们开始建造吧!

Flagsmith 帐户设置

  1. 如果您还没有账户,请访问https://app.flagsmith.com/signup并创建一个新账户。Flagsmith 还提供使用 Google 或 Github 的简单登录选项。
  2. 创建一个组织。为了方便本教程,我将其命名为“Flagsmith <-> Vercel”。您可以自行选择组织名称。
  3. 点击“创建项目”,在此组织内创建一个项目。我将其命名为“my-nextjs-project”。
  4. 恭喜!您已完成 Flagsmith 设置过程。您应该会看到一个屏幕,其中包含有关如何创建新功能的说明。

当我们想要将 Next.js 功能标志添加到我们的应用程序时,我们将回到此屏幕。

Github repo 设置

在https://github.com/上创建一个新的 repo 。我将其命名为“vercel-flagsmith-integration”。您可以随意重命名。

Vercel 帐户设置

  1. 访问https://vercel.com/signup,您可以轻松使用您的 Github 帐户注册
  2. 点击“添加新项目”->“项目”创建一个新项目。您可以直接访问https://vercel.com/new
  3. 在主页上,所有与该帐户关联的 Github 仓库都应该可见。确保已授予读取仓库的权限。最近创建的项目也应该显示在列表中。Vercel 会自动检测它是一个 Next.js 项目。
  4. 添加一些代码后我们将导入该项目

现在,让我们开始编码

创建一个 Next.js 入门项目

我们将使用create-next-appCLI 工具构建一个启动项目。参考:https://nextjs.org/docs/api-reference/create-next-app。在此基础上,我添加了一个基本的登录页面,以便我们能够接收一些用户输入,并在接下来的步骤中根据这些输入切换行为。

我们将使用 Vercel AppRouter 范例来构建我们的应用程序。

克隆此代码库即可查看代码https://github.com/abhishekag03/vercel-flagsmith-integration。请参阅拉取请求,逐步了解变更内容。具体来说,代码库的状态描述了当前的预期。

让我们部署吧!

  • 是时候再次访问我们的 Vercel 仪表板了 - https://vercel.com/new。单击刚刚推送的存储库旁边的“导入”按钮。
  • 立即点击“部署”按钮

部署完成后(通常只需几分钟),点击预览屏幕,即可跳转到已部署的网站。本例中的 DNS 为https://vercel-flagsmith-integration.vercel.app/

您可以访问项目的仪表板(通过单击上一节中的“继续到仪表板”)并查看域和其他各种设置

现在,我们推送到 repo“主”分支的任何更改都将近乎实时地部署在这里!

使用 Vercel 部署应用程序就是这么简单!

将 Flagsmith 与 Vercel 的力量结合起来

我们已经了解了设置和部署 Next.js 项目是多么容易。这对于基础项目来说已经足够好了——然而,在大多数情况下,我们希望对应用程序的行为有更多的控制。

例如,假设我们想在以下页面添加一张新卡片。目前该页面包含 4 张卡片:“文档”、“学习”、“模板”和“部署”。添加新卡片很简单,但对于大型应用程序来说,此类变更总是以增量方式推出的。它们会根据地理位置、类型或百分比进行推出。构建这种增量推出功能可能很棘手,因为它涉及管理大量实时更新的变量。

NextJS 起始页

这就是 Flagsmith 的作用所在。它提供了一个解决方案,让你只需单击一个按钮就可以在一个地方管理所有 Next.js 功能标志、A/B 测试和实验。

我们将看到使用 Flagsmith 向特定部分用户推出某项功能是多么容易。

我们想要的是:

  1. 访问网站时,用户应该可以选择输入自己的姓名并选择自己的职业
  2. 提交后,根据用户选择的职业,他们应该会看到下一个屏幕。
  3. 基于职业的屏幕行为应由 Flagsmith 控制台控制。
  4. 在 Flagsmith 控制台上动态更改职业列表,并在我们的网站上查看实时更新

将 Flagsmith 与 Next.js 应用程序集成

添加依赖项

我们需要先添加 flagsmith 包。运行以下命令:\



npm i flagsmith --save


Enter fullscreen mode Exit fullscreen mode

初始化 Flagsmith 客户端

现在,我们需要添加代码来初始化 flagsmith 客户端。

TL;DR -拉取请求

由于我们希望 Flagsmith 功能能够加载并呈现在状态中,因此我们将创建一个提供程序文件,用于加载标志状态并将其提供给我们的应用页面。这使我们能够使用 FlagsmithProvider。

因此,创建一个名为的文件app/provider.tsx。其中的内容应如下:



"use client";

import flagsmith from "flagsmith/isomorphic";
import { FlagsmithProvider } from "flagsmith/react";
import { IState } from "flagsmith/types";
import { ReactElement } from "react";

export default function Provider({
  children,
  flagsmithState,
}: {
  children: React.ReactNode;
  flagsmithState?: IState<string, string>;
}) {
  return (
    <FlagsmithProvider flagsmith={flagsmith} serverState={flagsmithState}>
      {children as ReactElement}
    </FlagsmithProvider>
  );
}


Enter fullscreen mode Exit fullscreen mode

Flagsmith 提供程序将允许其所有子组件通过useFlags钩子访问功能开关。在我们的示例中,我们将从服务器获取这些开关,并通过 serverState 属性将它们传递给提供程序。

我们将在我们的 中导入此提供程序app/layout.tsx file。这也是我们调用 init 函数来获取 Flagsmith 功能标志状态的地方。

添加 2 个导入,如下所示:



import Provider from "./provider";
import flagsmith from "flagsmith/isomorphic";


Enter fullscreen mode Exit fullscreen mode

RootLayout文件中的内容app/layout.tsx需要更新,如下所示:



export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const flagsmithState = await flagsmith
    .init({
      // fetches flags on the server
      environmentID: "heiEFz5x78igSLA8fGRgiP", // substitute your env ID
      identity: "my_user_id", // specify the identity of the user to get their specific flags
    })
    .then(() => {
      return flagsmith.getState();
    });
  return (
    <html lang="en">
      <body>
        <Provider flagsmithState={flagsmithState}>
          {children as ReactElement}
        </Provider>
      </body>
    </html>
  );
}


Enter fullscreen mode Exit fullscreen mode

请记住在layout.tsx文件中替换您环境特定的环境ID

要获取环境ID,请导航回 flagsmith 网站。

单击您的环境的“设置”,然后单击“密钥”。

Flagsmith SDK密钥

通过运行以下命令确保您仍然能够成功运行该应用程序:



yarn dev


Enter fullscreen mode Exit fullscreen mode

为“关于”页面创建新卡片

正如议程所述,我们将添加一张新卡。这张卡将根据用户职业/细分市场分阶段推出。

TL;DR:拉取请求

可以将以下代码添加到app/about/Page.tsx文件内的 Page() 函数中以获取此新卡。



<a
  href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
  className={styles.card}
  target="_blank"
  rel="noopener noreferrer"
>
  <h2 className={inter.className}>
    Configure <span>-&gt;</span>
  </h2>
  <p className={inter.className}>
    Configure your feature rollout with&nbsp;Flagsmith
  </p>
</a>


Enter fullscreen mode Exit fullscreen mode

一旦合并并部署此代码,所有访问我们网站的用户都可以看到此更改。

然而,这并非我们想要的。作为委托人,新功能是逐步添加的。如果“配置”链接坏了怎么办?如果配置流程出现问题怎么办?如果用户开始讨厌“配置”卡片,而我们想将其移除怎么办?

如果我告诉您,只需单击一下即可实现所有这些控制,您会怎么想?

让我们添加一个分阶段推出的机制,以便只有职业为“自由职业者”的用户才会首先看到这张卡片。

为此,我们需要在 Flagsmith 仪表板上添加一个新功能。

创建特征

点击下面的“创建您的第一个功能”选项:

在 Flagsmith 中创建功能

我将该功能命名为“configure_card_controller”,因为它控制名为“Configure”的卡

创建特征

创建段覆盖

让我们编辑此功能并创建一个细分覆盖。细分覆盖本质上允许您根据用户的特征配置功能标记行为。在本例中,我们将使用“职业”作为特征。

点击该功能,然后导航至“细分覆盖”选项卡。点击“创建特定于功能的细分”

为具有 的用户添加覆盖profession = freelancer

使用 Flagsmith 创建片段

也可以为项目全局创建段,但在这种情况下,我们只想为这一个功能创建段覆盖。

段覆盖允许您指定功能的启用状态和远程配置。您可以根据需要向功能添加任意数量的段覆盖,覆盖的优先级由其顺序决定。

创建段覆盖

现在,段覆盖已添加,请将其启用并保存。请注意,默认情况下该功能处于关闭状态,我们仅为此段启用了此功能。

开启段覆盖功能

带有 Flagsmith 的控制卡

TL;DR - 请参阅此 Pull 请求以了解代码更改 - https://github.com/abhishekag03/vercel-flagsmith-integration/pull/11

添加以下导入到app/about/page.tsx



import { useFlags } from "flagsmith/react";


Enter fullscreen mode Exit fullscreen mode

通过告诉它需要读取哪个功能标志键来初始化标志变量



// only causes re-render if specified flag values change
const flags = useFlags(["configure_card_controller"]); 


Enter fullscreen mode Exit fullscreen mode

现在,将新添加的卡片(“配置”卡片)包装在一个条件中,以检查此标志。

我们读取标志值的方式是:



flags.configure_card_controller.enabled


Enter fullscreen mode Exit fullscreen mode

为了有条件地查看配置卡,我们只需将该卡标记括在以下内容中:



{flags.configure_card_controller.enabled &&
    (
      <a 
        ... // the card segment code
      </a>
    )}


Enter fullscreen mode Exit fullscreen mode

为了在用户到达此屏幕时获得适当的屏幕,我们需要确保标志特征得到适当设置。

我们将修改该handleOnSubmit函数来设置特征。

将下面的导入和以绿色突出显示的行添加到文件handleOnSubmit内的函数中app/page.tsx

以下代码trait根据用户选择设置 Flagsmith 值。设置特征是异步的,它会获取最新的标志,并考虑用户可能因该特征而产生的任何新的段覆盖。



import flagsmith from "flagsmith/isomorphic";

const handleOnSubmit = async(e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    await flagsmith.setTrait("profession", user.position); // setting the "profession" trait as the one selected by user

 router.push("/about?name=" + user.name + "&position=" +   user.position);
  };


Enter fullscreen mode Exit fullscreen mode

我们需要useRouter来获取从登录页面传递过来的信息。

我们需要指定代码中要使用的标志和特征。如上所示,我们使用了“configure_card_controller”标志和“profession”特征。这使得标志变量与这些名称紧密耦合,从而降低了编码时出错的几率。

测试和实验

将此代码部署到 Vercel 并开始测试。

请注意,当您选择自由职业者作为职业时,您将看到 5 张卡片。其中应该包含“配置”卡片。

选择任何其他职业时,仅显示 4 张卡片:

您可能会想,这可以通过一个简单的 if/else 条件来实现 - 为什么我们需要 Flagsmith?

Flagsmith 允许您动态控制这些配置,而无需任何代码更改或重新部署。

例如,如果我们看到这张新卡牌反响良好,我们可能会想把它扩展到其他职业。为此,我们只需前往旗匠界面并添加新的职业名称即可。

让我们尝试一下 - 更新该部分以允许“设计师”职业看到这张新卡片。

编辑该片段并添加职业条件 = “设计师”。

重新部署后,您可以看到自由职业者和设计师都能看到这张新卡片。第三个职业(前端开发人员)仍然可以看到这 4 张卡片。

让我们推送此代码并将其部署到我们的主站点。

在 Vercel 中查看我们的功能标志

代码现已上线,我们可以根据需要随时更新用户细分并推出。您可以在https://vercel-flagsmith-integration.vercel.app/上测试运行。

无需任何拉取请求、代码修改、重新部署或测试,我们就能改变网站的行为。这是一个非常强大的集成,可以广泛应用于各种规模的项目。

结论

总而言之,通过本文,我们展示了功能开关在 Vercel 上托管的 Next.js 项目中的实际应用和重要性。通过集成 Flagsmith,我们展示了 Next.js 功能开关如何帮助开发者降低部署风险、安全地进行实验并提供个性化的用户体验。动态更新和段覆盖的便捷性凸显了功能开关在无需更改代码或重新部署的情况下提供的灵活性和控制力。通过这种实践方法,您可以根据用户反馈微调功能的推出并调整应用程序,从而使功能开关成为迭代和以用户为中心的开发的宝贵工具。拥抱功能开关,解锁新的可能性,并在您的软件项目中提供卓越的用户体验。

希望您发现这篇文章很有用,并且这种集成可以帮助您构建应用程序!

鏂囩珷鏉ユ簮锛�https://dev.to/kylessg/implementing-feature-flags-with-nextjs-and-app-router-1gl8
PREV
一个业余项目如何帮助我实现薪水翻倍 Android-Static-Security-Audit
NEXT
使用 Next 和 Redux next.js 获得完美的 100% Google Lighthouse 审核分数 我很无聊,只需将代码发送给我。1. next.js 与 Redux 2. 获得 100% 的 Lighthouse 分数 结果