1727302883
2024-09-25 08:59:31
実際のプロジェクトで Next.js App Router を使用する場合、機能フラグを実装する必要がある場合があります。機能フラグは、新しいコードをデプロイせずにアプリケーションの機能を有効または無効にできる手法です。これは、新しい機能をテストしたり、機能を段階的に展開したり、バグを修正したりするのに役立ちます。
Vercelは最近、独自の 機能フラグソリューションただし、さまざまな理由から、独自の機能フラグ設定ソリューションを実装する必要がある場合があります。私の場合、展開に Vercel を使用しておらず、Azure 上の App Service を通じて基本的な機能フラグ設定ソリューションが必要なだけです。
このブログ記事では、Next.js App Router を使用して機能フラグの簡易版を実装する方法を紹介します。私は機能フラグの専門家ではないので、このアプローチについてのフィードバックをお待ちしています。私のユースケースではうまく機能しますが、もっと良い方法があるはずです。
目次
目次を開く
環境変数の設定
環境変数を使用して、特定の機能をオンまたはオフにしたいと考えています。TEMPLATE、MESSAGES、FORWARDING という 3 つの実験的な機能があるとします。環境変数を使用して、これらの機能をオンまたはオフにできるようにしたいと考えています。
これを実現するには、 .env プロジェクトのルートにあるファイル。環境変数を設定する方法の例を次に示します。
...
FEATURE_TEMPLATES=1
FEATURE_MESSAGES=1
FEATURE_FORWARDING=0
これらの環境変数は、Next.jsアプリケーションで次のように利用できます。 process.envこれらは、App Service またはその他のデプロイ環境で設定できます。環境変数が「1」に設定されていない機能は、デフォルトでオフになります。
Yupで機能スキーマを作成し、環境変数をエクスポートする
フィーチャスキーマを作成するには、 うん 環境変数を検証します。同等のメソッドを持つ Zod を使用することもできます。これにより、機能フラグ付けに使用する環境変数以外の環境変数が公開されないようにすることができます。
export const featureSchema = Yup.object({
FEATURE_TEMPLATES: Yup.string(),
FEATURE_MESSAGES: Yup.string(),
FEATURE_FORWARDING: Yup.string(),
});
export type FeatureSchemaType = Yup.InferTypetypeof featureSchema>;
次に、 env.mjs 環境変数を検証するファイル:
import { featureSchema } from '@/validations/envSchema';
export const featureEnv = featureSchema.validateSync({
FEATURE_TEMPLATES: process.env.FEATURE_TEMPLATES,
FEATURE_MESSAGES: process.env.FEATURE_MESSAGES,
FEATURE_FORWARDING: process.env.FEATURE_FORWARDING,
});
今、私たちは featureEnv アプリケーション内の環境変数にアクセスするためのオブジェクト。
サーバーコンポーネントの機能の切り替え
これで、環境変数を使用してサーバー コンポーネントの機能を切り替えることができます。これを簡素化する関数を作成しましょう。
import type { FeatureSchemaType } from '@/validations/envSchema.js';
import { featureEnv } from '../../env.mjs';
export async function getFeature(feature: keyof FeatureSchemaType): Promiseboolean> {
return featureEnv[feature] === '1';
}
これは、サーバー コンポーネントで簡単に使用できます。コンポーネント/機能自体で機能を制御したり、さまざまなレイアウトでコンポーネントを非表示/表示したりできます。
export default async function Messages() {
const isEnabled = await getFeature('FEATURE_MESSAGES');
return isEnabled ? (
div>
h1>Messagesh1>
div>
) : null;
export default async function Page() {
const messagesIsEnabled = await getFeature('FEATURE_MESSAGES');
return (
div>
{messagesIsEnabled && Messages />}
div>
);
環境変数を変更することで、App Service または関連するデプロイ環境の機能をオンまたはオフにできるようになりました。ページを更新すると、機能がオンまたはオフに切り替わります。
クライアントコンポーネントの機能の切り替え
クライアント側なので、環境変数に直接アクセスすることはできません。しかし、ライブで機能をオン/オフできる柔軟性は必要です。ここでの最初の解決策は、機能フラグをプロパティとしてクライアント コンポーネントに渡すことです。ただし、コンポーネント ツリー内の複数のコンポーネントに機能フラグを渡す必要がある場合があるため、これは理想的ではありません。
代わりに、クライアント コンポーネントに機能フラグを提供する機能プロバイダーを作成しましょう。
'use client';
import React, { createContext } from 'react';
import type { FeatureSchemaType } from '@/validations/envSchema';
type FeatureContextType = {
features: FeatureSchemaType;
};
const FeatureContext = createContextFeatureContextType | undefined>(undefined);
export default function FeatureProvider({
features,
children,
}: {
features: FeatureSchemaType;
children: React.ReactNode;
}) {
return (
FeatureContext.Provider
value={{
features,
}}
>
{children}
FeatureContext.Provider>
);
}
export function useFeature(feature: keyof FeatureSchemaType) {
const context = React.useContext(FeatureContext);
if (context === undefined) {
throw new Error('useFeature must be used within a FeatureProvider');
}
return context.features[feature] === '1';
}
これをルート レイアウトで使用して、サーバーから機能フラグを渡すことができます。
...
import { featureEnv } from '../../env.mjs';
export default async function RootLayout({ children }: { children: React.ReactNode }) {
return (
FeatureProvider featureEnv={featureEnv}>
{children}
FeatureProvider>
);
}
これで、 useFeature クライアントコンポーネントにフックを組み込み、 getFeature サーバーコンポーネント内の機能:
'use client';
...
export default function Messages() {
const isEnabled = useFeature('FEATURE_MESSAGES');
オンまたはオフに切り替えたい機能を備えたサイドバーがあるとします。サイドバー項目ごとに機能の名前を割り当てることができます。
export type RouteObject = {
name: string;
path: string;
icon?: React.ReactNode;
isAuthenticated?: boolean;
feature?: keyof FeatureSchemaType;
};
...
{ icon: HelpIcon />, name: 'help', path: routes.help() },
{
feature: 'FEATURE_TEMPLATES',
icon: DocIcon />,
isAuthenticated: true,
name: 'templates',
path: routes.templates(),
},
...
サイドバーは次のようになります。
ul>
{visibleRoutes.map(item => {
if (item.isAuthenticated && !isAuthenticated) {
return null;
}
return (
SidebarItem
feature={item.feature}
key={item.path}
name={item.name}
icon={item.icon}
path={item.path}
/>
);
})}
ul>
次に、この機能が有効になっているかどうかを確認します。 SidebarItem 成分:
type Props = {
...
feature?: keyof FeatureSchemaType;
};
export default function SidebarItem({ feature }: Props) {
const isEnabled = useFeature(feature);
return isEnabled ? (
li>
Link>
...
Link>
li>
) : null;
}
これはうまく機能します。しかし、私たちは常に機能フラグのないアイテムを表示したいのです。デフォルトの機能フラグを featureSchema:
export const featureSchema = Yup.object({
FEATURE_DEFAULT: Yup.string().default('1'),
FEATURE_MALER: Yup.string(),
FEATURE_MELDINGER: Yup.string(),
FEATURE_VIDERESENDING: Yup.string(),
});
これで、 FEATURE_DEFAULT フラグをデフォルト値として SidebarItem 成分:
export default function SidebarItem({ feature = 'FEATURE_DEFAULT' }: Props) {
const isEnabled = useFeature(feature);
return isEnabled ? (
li>
Link>
...
Link>
li>
) : null;
}
また、サイドバーには機能フラグのない項目が常に表示されます。
結論
このブログ記事では、Next.js App Router を使用してシンプルな機能フラグを実装する方法を紹介しました。環境変数を使用して、サーバー コンポーネントとクライアント コンポーネントの両方で機能を切り替えました。
この投稿がお役に立てば幸いです。ご質問やご意見がありましたらお知らせください。また、フォローしてください。 ツイッター 最新情報についてはこちらをご覧ください。コーディングを楽しみましょう! 🚀
#Next.js #アプリルーターを使用した機能フラグの実装