UpstashRedisをRemixで使用する
Remixは、フルスタックのReactフレームワークであることの意味を新たに取り入れたものであり、既存のWeb標準に焦点を当て、フロントエンドをバックエンドに密接に結び付けています。この緊密な結合は、Reactコンポーネントにデータをロードするのがいかに簡単であるか、またはフォームから送信されたデータを処理する方法を見ると、新鮮な空気の息吹です。
この記事では、UpstashRedisをデータベースとして使用してシンプルな機能フラグ管理システムを作成することでRemixの力を紹介します。
完全なソースコードはここにあります。
npx create-remix@latest
を実行すると、まったく新しいRemixアプリを入手できます。 好みの展開環境を選択します。 Vercelを使用しましたが、このチュートリアルでは違いはありません。
Upstash Redisに接続する方法は2つあります。1つは、使い慣れた標準のRedisクライアントライブラリを使用できるTCP接続を使用する方法です。 2つ目は、UpstashのRESTAPIを介したものです。 RemixをデプロイできるCloudflareWorkers環境など、すべてのサーバーレス環境で利用できるため、2番目のオプションを使用します。 Upstashには、実際のRedisコマンドを模倣したパッケージがあり、呼び出す関数を簡単に知ることができます。
ここで、UpstashRedisデータベースに接続するために必要な2つの環境変数を格納する方法が必要です。 Remixには、すぐに使用できる開発環境変数のサポートは付属していませんが、開発依存関係としてdotenvを追加することで実現できます。
npm add --save-dev dotenv
.env
で ファイル(.gitignore
に追加する必要があります )UpstashRedisに接続するために必要な2つのenv変数を設定できます。 @upstash/redis
パッケージはこれらを自動的に検出するため、コード内で接続する必要はありません。これらの値は、新しいRedisデータベースを作成した後のUpstashダッシュボード内で確認できます。
UPSTASH_REDIS_REST_URL="https://..."
UPSTASH_REDIS_REST_TOKEN="..."
dev
を更新する必要があります dotenvにenv変数を取得させるスクリプト。他のスクリプトは同じままにすることができます。
{
"scripts": {
"dev": "node -r dotenv/config node_modules/.bin/remix dev"
}
}
機能フラグは非常に複雑になる可能性があり、ユーザーベースのパーセンテージへの展開計画が特定のユーザーグループに対して有効になりますが、「オン」と「オフ」のように単純にすることもできます。 Redisが提供するハッシュデータ型を使用して機能フラグを保存します。データは以下のJSONのようになり、「1」が有効/オン、「0」が無効/オフになります。
{
"chart": "1",
"graph": "0"
}
このデータにアクセスして操作するには、Redisが提供する4つのコマンド/関数を使用します。
- hgetallは、すべてのキー(機能)と値(有効/無効)を取得します。
- hsetは特定の機能フラグを有効または無効にします。
- hdelを使用して特定の機能フラグを削除します。
- 複数の特定の機能フラグ値を一度に取得するためのhmget。
/features
にあるページを作成します これは、既存の機能の作成と管理(有効化/無効化/削除)を担当します。 AddFeature
について詳しく説明します およびFeatureList
データの読み込み方法とデータの書き込み方法について話し合うときに行います。
// app/routes/features.tsx
export default function Features() {
return (
<div>
<h1>Features</h1>
<AddFeature />
<FeatureList />
</div>
);
}
データローダーは、loader
という名前のRemixでエクスポートされた関数です。 これはサーバー上で実行され、フックを介してReactコンポーネントで利用できるようになったデータを返します。
機能フラグを作成および管理するページから始めます。この場合、すべての機能を返します。それらはペアの配列として返されます:
[
["graph", true],
["chart", false]
]
TypeScriptタイプ定義から始めて、loadAllFeatures
という関数が表示されます。 hgetall
を使用します @upstash/redis
からの関数 。
import { Redis } from "@upstash/redis";
type LoaderData = {
features: Array<[string, boolean]>;
};
const loadAllFeatures = async () => {
const redis = Redis.fromEnv();
const data = await redis.hgetall("features");
const features: Array<[string, boolean]> = [];
for (let i = 0; i < data.length; i += 2) {
features.push([data[i], data[i + 1] === "1"]);
}
return features.sort((a, b) => {
if (a[0] > b[0]) return 1;
if (a[0] < b[0]) return -1;
return 0;
});
};
エクスポートされたloader
関数自体がloadAllFeatures
を呼び出します 関数、Reactコンポーネントに渡される機能を返します。
export const loader: LoaderFunction = async (): Promise<LoaderData> => {
// You would want to add authentication/authorization here
const features = await loadAllFeatures();
return { features };
};
このReactコンポーネントの詳細については後で説明しますが、ローダー関数から返されたデータにアクセスする方法を示すために、useLoaderData
と呼ばれるRemixフックを使用します。 。
const FeatureList = () => {
const { features } = useLoaderData<LoaderData>();
return (
<ul>
{features.map(([feature, active]) => (
<li key={feature}>{/* coming soon */}</li>
))}
</ul>
);
};
データがどのように読み込まれるかを見てきましたが、この段階では、機能フラグデータベースに実際には機能がありません。ここでフォームアクションが機能します。 action
という名前の関数をエクスポートすることにより、Remixでデータが処理されます。 。 loader
によく似ています 、これはサーバー上で実行され、通常はjson
を返します Reactコンポーネントが別のフックを介してアクセスできるデータ、またはブラウザにredirect
するように指示できるデータ 別のページに移動します。
action
以下の関数は、実際には、機能の作成、機能の有効化/無効化、および機能の削除という4つの異なるタイプのアクションを処理します。これはswitch
で処理します 次に、適切なRedis関数/コマンドを呼び出すステートメント。
export const action: ActionFunction = async ({ request }) => {
// You would want to add authentication/authorization here
const formData = await request.formData();
const feature = formData.get("feature") as string;
const action = formData.get("_action") as string;
if (!feature || feature.length === 0) {
// This isn't currently displayed in our component
return json({ error: "Please provide a feature" });
}
switch (action) {
case "create":
case "enable":
await redis.hset("features", { [feature]: 1 });
break;
case "disable":
await redis.hset("features", { [feature]: 0 });
break;
case "delete":
await redis.hdel("features", feature);
break;
}
return redirect("/features");
};
成功すると、ユーザーが現在表示しているのと同じページにリダイレクトすることに気付くでしょう。これは基本的にページのリロードをトリガーし、loader
を呼び出します 機能し、ユーザーに表示される内容を更新します。
新しい機能フラグを追加するには、AddFeature
コンポーネントはRemixForm
を使用します 上記のアクション関数にデータを送信するコンポーネント。 post
経由で送信するように指定しました メソッドとreplace
も提供しました 機能フラグを作成するたびにブラウザの履歴に新しいページが追加されないようにするための小道具。
const AddFeature = () => {
return (
<Form method="post" replace>
<input type="hidden" name="_action" value="create" />
<input type="text" name="feature" required placeholder="name" />
<button type="submit">Add</button>
</Form>
);
};
機能が作成されたら、管理できるように現在のすべての機能フラグを表示する必要があります。各機能フラグには、実際には2つの形式が表示されます。1つは機能フラグを有効/無効にするためのもので、もう1つは機能フラグを削除するためのものです。
_action
という2つの非表示フィールドがあることに注意してください。 action
functionは、機能に対して何をしようとしているのか、およびfeature
を認識しています。 変更するフラグ名を送信します。
const FeatureList = () => {
const { features } = useLoaderData<LoaderData>();
return (
<ul>
{features.map(([feature, active]) => (
<li key={feature}>
<Form method="post" replace>
<input
type="hidden"
name="_action"
value={active ? "disable" : "enable"}
/>
<input type="hidden" name="feature" value={feature} />
<button type="submit" className="btn-naked">
{active ? "💪" : "🦾"}
</button>
</Form>
<span>{feature}</span>
<Form method="post" replace>
<input type="hidden" name="_action" value="delete" />
<input type="hidden" name="feature" value={feature} />
<button type="submit">Delete</button>
</Form>
</li>
))}
</ul>
);
};
Upstash Redisデータベースには機能フラグがありますが、これらのフラグに基づいてアプリの機能のオンとオフを切り替えないのは良いことです。ローダー関数を使用して、hmget
を使用してデータベースから特定の機能をロードします 、次にデータを少し操作して適切な構造にします。
["chart", "graph", "fake"]
をロードする場合 フラグ、Redisは["1", "0", null]
を返します ...フラグが存在しない場合、その値はnull
になることに注意してください。 、fake
を含めて表示したかった フラグ。
type LoaderData = {
features: Record<string, boolean>;
};
const loadFeatures = async (keys: Array<string>) => {
const data = await redis.hmget("features", ...keys);
const features = keys.reduce<Record<string, boolean>>((acc, key, index) => {
acc[key] = data[index] === "1";
return acc;
}, {});
return features;
};
export const loader: LoaderFunction = async (): Promise<LoaderData> => {
const features = await loadFeatures(["chart", "graph"]);
return { features };
};
これで、RemixのuseLoaderData
を使用して、コンポーネントにロードされたデータにアクセスできるようになりました。 針。次に、フラグが現在有効か無効かを考慮して、Webサイトの機能をどのように変更するかを選択します。
export default function Index() {
const { features } = useLoaderData<LoaderData>();
return (
<div>
<h1>Dashboard</h1>
{features.chart ? <h2>Chart</h2> : <h2>No Chart</h2>}
{features.graph ? <h2>Graph</h2> : <h2>No Graph</h2>}
</div>
);
}
この記事では、Upstash Redisを使用して、データローダーとフォームアクションサーバー側の機能を利用して、Remixでシンプルな機能フラグシステムを作成する方法を説明しました。これらにより、特定のページのバックエンドとフロントエンドを緊密に結合し、個別のGraphQL APIを設定したり、フロントエンドで標準のフォーム送信イベントをオーバーライドしたりすることなく、すばやく反復することができます。これまで見てきたように、リミックスは、フォームがデータを送信する方法に関するWeb標準に依存しています。
-
UpstashRedisを使用したNetlifyグラフのグローバルキャッシュ
昨日、NetlifyはNetlify Graphと呼ばれる新機能を発表しました。私の同僚は最近、写真の同様の欠落部分を強調し、Netlifyは解決に向けて良い一歩を踏み出しました。 基本的に、Netlify Graphは、開発者がWebアプリのGraphQL API呼び出しを構築するのに役立ちます。NetlifyDashboardでGraphQLリクエストを準備した後、シングルクリックでクライアントコードをプロジェクトに挿入できます。 Netlify関数をサードパーティサービスと一緒に使用することには欠点があります。クライアント側のリクエストは、最初にNetlifyバックエンド(関数)に送
-
CloudflareワーカーとのRedis@Edge
エッジでのコンピューティングは、近年最もエキサイティングな機能の1つです。 CDNを使用すると、ファイルをユーザーに近づけることができます。エッジコンピューティングを使用すると、アプリケーションをユーザーの近くで実行できます。これは、開発者がグローバルに分散されたパフォーマンスの高いアプリケーションを構築するのに役立ちます。 Cloudflare Workersは、現在この分野の主要製品です。コールドスタートのないサーバーレス処理環境を提供します。 Cloudflareのグローバルネットワークを活用して、アプリケーションのレイテンシーを最小限に抑えます。関数はJavascript、Rust、