UpstashRedisをRemixのセッションストアとして使用する
フルスタックのWebフレームワークとして、Remixは一般的なWebサーバーのユースケースを処理するためのAPIを提供します。この投稿では、セッションと、Upstashを使用してセッションを保存する理由と方法に焦点を当てます。
セッションとは何ですか?
Remixドキュメントには、セッションの非常に優れた紹介がありますhttps://remix.run/docs/en/v1/api/remix#sessions
一言で言えば、セッションは、サーバーとクライアントがユーザーデータ/状態を共有できるようにするメカニズムです。セッションの使用例としては、ユーザー認証の状態、ショッピングカートのステータス、フラッシュメッセージなどの追跡があります。
UpstashRedisを使用する理由
セッションデータはサーバーに保存されます。サーバーレスインフラストラクチャまたは一部のPASSインフラストラクチャ(Herokuなど)にデプロイする場合、リクエスト(サーバーレス)またはデプロイ(PASS)ごとにデータが変更される可能性があるため、サーバーのファイルシステムにデータを永続化することはできません。データを永続化するには、ユーザーデータを外部データベースに保存する必要があります。 Upstash Redis DBは、次の理由でセッションデータを保存するための優れたソリューションです。
- Redisセッションと同様に、本質的に
key:value
があります キーがセッションのIDであり、値がシリアル化されたデータであるデータ構造。 - Redisには、期限切れのセッションをクリーンアップする必要性を減らす組み込みの期限切れメカニズムがあります。
- セッションは機密性の高いユーザーデータを保持する場合があり、UpstashRedisは保存されているすべてのデータを暗号化します。
- Upstashは単純なHTTPRESTAPIを使用しています。 HTTPは、サーバーレスインフラストラクチャから通信する最も簡単な方法です。
RedisでUpstashをセッションプロバイダーとして使用する方法
この投稿は、私が書いたUpstashの例を使用したRedisセッションストレージに基づいています。 Remixリポジトリのクローンを作成して、試してみてください。
- https://upstash.com/にアクセスして新しいアカウントを作成します
- 新しいRedisDBを作成する
-
UPSTASH_REDIS_REST_URL
をコピーします &UPSTASH_REDIS_REST_TOKEN
それらを.env
というファイルに保存します Remixプロジェクトのルートにあります。 -
dotenv
をインストールします -$ npm install --save-dev dotenv
-これにより、.env
から環境変数を挿入できるようになります 作成したファイル。 - Go to you
package.json
ファイルを作成し、dev
を置き換えます スクリプトフォームremix dev
dotenv/config node_modules/.bin/remix dev
へ 。
ステップ2-コアのcreateSessionStorage
を実装します Upstashセッションの実装を作成するには
Remixは、createSessionStorage
を使用して独自のセッション統合を構築するための優れたAPIを提供します 。この関数を実装してUpstashを統合しましょう。
// sessions/upstash.server.ts
import * as crypto from "crypto";
import { createSessionStorage } from "remix";
const upstashRedisRestUrl = process.env.UPSTASH_REDIS_REST_URL;
const headers = {
Authorization: `Bearer ${process.env.UPSTASH_REDIS_REST_TOKEN}`,
Accept: "application/json",
"Content-Type": "application/json",
};
const expiresToSeconds = (expires) => {
const now = new Date();
const expiresDate = new Date(expires);
const secondsDelta = expiresDate.getSeconds() - now.getSeconds();
return secondsDelta < 0 ? 0 : secondsDelta;
};
// For more info check https://remix.run/docs/en/v1/api/remix#createsessionstorage
export function createUpstashSessionStorage({ cookie }: any) {
return createSessionStorage({
cookie,
async createData(data, expires) {
// Create a random id - taken from the core `createFileSessionStorage` Remix function.
const randomBytes = crypto.randomBytes(8);
const id = Buffer.from(randomBytes).toString("hex");
// Call Upstash Redis HTTP API. Set expiration according to the cookie `expired property.
// Note the use of the `expiresToSeconds` that converts date to seconds.
await fetch(
`${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
{
method: "post",
body: JSON.stringify({ data }),
headers,
}
);
return id;
},
async readData(id) {
const response = await fetch(`${upstashRedisRestUrl}/get/${id}`, {
headers,
});
try {
const { result } = await response.json();
return JSON.parse(result).data;
} catch (error) {
return null;
}
},
async updateData(id, data, expires) {
await fetch(
`${upstashRedisRestUrl}/set/${id}?EX=${expiresToSeconds(expires)}`,
{
method: "post",
body: JSON.stringify({ data }),
headers,
}
);
},
async deleteData(id) {
await fetch(`${upstashRedisRestUrl}/del/${id}`, {
method: "post",
headers,
});
},
});
}
今書いたことを説明しましょう:sessions/upstash.server.ts
という名前のファイルを作成しました 。このファイルは、createUpstashSessionStorage
という名前の関数をエクスポートします 。この関数は、パラメータとしてcookie
を取ります。 (これについては後で詳しく説明します)そしてコアRemix createSessionStorage
を使用します 新しいセッションプロバイダーを実装するためのファクトリ関数。
関数内にcreateSessionStorage
を実装しました 新しいセッションを作成するためのプロトコル(createData
)、セッション値を読み取ります(readData
)、セッション値を更新します(updateData
)そしてセッションを削除します(deleteData
。
各関数はREST
を使用します Redisデータベースと対話するためのUpstashAPI。
- 渡されたCookieは
cookie expiration date
を保持しますjs Date
で フォーマット。expiresToSeconds
を使用します これはRedisが期待するものであるため、データを秒に変換する関数。 - Cookieを設定するときは、有効期限を設定することを忘れないでください。期限切れになると、Redisはそれらのセッションを自動的に削除します。
-
crypto
を使用します 一意のセッションIDを作成します。一意のIDを作成するために他の方法を使用できます。このオプションを選択したのは、コアのcreateFileSessionStorage
で使用されているものと同じであるためです。 機能。
ステップ3-createSessionStorage
を使用します アプリで
これで、独自のセッションストレージ実装を作成し、その使用方法をデモンストレーションできます。
今後、Upstashに固有のものは何もないことに注意してください。すべてのロジックは
sessions/upstash.server.ts
にカプセル化されています ファイル。
// sessions.server.ts
import { createCookie } from "remix";
import { createUpstashSessionStorage } from "~/sessions/upstash.server";
// This will set the length of the session.
// For the example we use a very short duration to easily demonstrate its functionally.
const EXPIRATION_DURATION_IN_SECONDS = 10;
const expires = new Date();
expires.setSeconds(expires.getSeconds() + EXPIRATION_DURATION_IN_SECONDS);
const sessionCookie = createCookie("__session", {
secrets: ["r3m1xr0ck1"],
sameSite: true,
expires,
});
const { getSession, commitSession, destroySession } =
createUpstashSessionStorage({ cookie: sessionCookie });
export { getSession, commitSession, destroySession };
sessions.server.ts
という名前のファイルを作成します 上記のコードを貼り付けます。このファイルは、3つの関数getSession
をエクスポートします。 、commitSession
およびdestroySession
。これらの機能により、アプリはセッションと対話できます。また、クライアントのセッションへの参照を保存するためのCookieを作成しました。
ビジネスニーズに応じて有効期限を設定します。詳細については、https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
をお読みください。
Remixを使用すると、ルートごとのセッション使用量を定義できます。次の例では、session
を使用します routes/index.tsx
で 。この例は、セッションAPIの使用方法のみを示しています。セッションを特定のビジネスロジックに接続することは、この投稿の範囲外です。
認証にセッションを使用する方法の例を探している場合は、https://github.com/remix-run/remix/tree/main/examples/remix-auth-form
を参照してください。
// routes/index.tsx
import type { LoaderFunction } from "remix";
import { json, useLoaderData } from "remix";
import { commitSession, getSession } from "~/sessions.server";
export const loader: LoaderFunction = async ({ request }) => {
// Get the session from the cookie
const session = await getSession(request.headers.get("Cookie"));
const myStoredData = session.get("myStoredData");
// If no session found (was never created or was expired) create a new session.
if (!myStoredData) {
session.set("myStoredData", "Some data");
return json(
{
message: "Created new session",
},
{
headers: {
"Set-Cookie": await commitSession(session),
},
}
);
}
// If session was found, present the session info.
return json({
message: `Showing Session info: ${myStoredData}`,
});
};
export default function () {
const data = useLoaderData();
return <div>{data.message}</div>;
}
この例は、ユーザーセッションの2つの可能な状態(ユーザーがセッションを持っているか、ユーザーがセッションを持っていない)を処理する方法を示しています。ユーザーがセッションを持っていない場合、アプリのインデックスファイルに移動すると、新しいセッションが作成され、ダミーデータが保存されます。ユーザーが有効な(期限切れではない)セッションを持っている場合、ルートにはセッションのデータが表示されます。
Upstashを使用してセッションを実装したので、選択した展開戦略を自由に選択できます。
Upstash環境変数を設定することを忘れないでください。
createFileSessionStorage
の使用 ローカル開発およびcreateUpstashSessionStorage
ステージング/制作中
オフラインで開発できるようにしたいと思うかもしれません。ローカルで開発する場合は、createUpstashSessionStorage
を置き換えることができます createFileSessionStorage
を使用 現在のNODE_ENV
を検出する 。
Upstashの実装が機能することをテストした後、sessions/upstash.server.ts
を変更します 次のようにファイルします:
このセクションを変更します:
// from sessions/upstash.server.t
const { getSession, commitSession, destroySession } =
createUpstashSessionStorage({ cookie: sessionCookie });
あり:
// from sessions/upstash.server.ts
const { getSession, commitSession, destroySession } = (process.env.NODE_ENV === "development") ?
createFileSessionStorage({ cookie: sessionCookie, dir: './sessions' });
: createUpstashSessionStorage({ cookie: sessionCookie });
これで、ローカルで開発する場合、Upstashを呼び出す代わりにローカルファイルシステムを使用します。
この投稿では、UpstashRedisDBを使用してセッションストレージデータをホストする方法を説明しました。 Remix APIは、特定のセッションストレージの実装を非常にうまくカプセル化し、統合を前進させます。この例を試してみたい場合は、https://github.com/remix-run/remix/tree/main/examples/redis-upstash-session
のRemixソースコードで確認できます。お楽しみください。
-
TODOアプリをRedisでリミックスする
この投稿では、RemixとサーバーレスRedis(Upstash)を使用して簡単なTODOアプリを作成します。 Remixはフルスタックのウェブフレームワークであり、ユーザーインターフェースに集中し、ウェブの基本をやり直して、高速で洗練された復元力のあるユーザーエクスペリエンスを提供できます。 リミックスプロジェクトを作成 次のコマンドを実行します: npx create-remix@latest プロジェクトの準備が整いました。それでは、依存関係をインストールして実行しましょう: npm install npm run dev ユーザーインターフェース 簡単なフ
-
UpstashRedisを使用したNetlifyグラフのグローバルキャッシュ
昨日、NetlifyはNetlify Graphと呼ばれる新機能を発表しました。私の同僚は最近、写真の同様の欠落部分を強調し、Netlifyは解決に向けて良い一歩を踏み出しました。 基本的に、Netlify Graphは、開発者がWebアプリのGraphQL API呼び出しを構築するのに役立ちます。NetlifyDashboardでGraphQLリクエストを準備した後、シングルクリックでクライアントコードをプロジェクトに挿入できます。 Netlify関数をサードパーティサービスと一緒に使用することには欠点があります。クライアント側のリクエストは、最初にNetlifyバックエンド(関数)に送