เนื่องจาก Remix เว็บเฟรมเวิร์กแบบเต็มสแต็กมี API เพื่อจัดการกับกรณีการใช้งานเว็บเซิร์ฟเวอร์ทั่วไป โพสต์นี้จะเน้นที่เซสชันและสาเหตุ และวิธีที่คุณสามารถใช้ Upstash เพื่อจัดเก็บได้
เซสชันคืออะไร
เอกสาร Remix มีการแนะนำเซสชันที่ดีมาก https://remix.run/docs/en/v1/api/remix#sessions
พูดได้ไม่กี่คำ - เซสชันเป็นกลไกที่ช่วยให้เซิร์ฟเวอร์และไคลเอนต์สามารถแบ่งปันข้อมูล / สถานะของผู้ใช้ ตัวอย่างการใช้งานเซสชัน ได้แก่ การติดตามสถานะการตรวจสอบสิทธิ์ของผู้ใช้ สถานะตะกร้าสินค้า ข้อความแฟลช ฯลฯ
เหตุใดจึงต้องใช้ Upstash Redis
ข้อมูลเซสชันถูกเก็บไว้บนเซิร์ฟเวอร์ เมื่อปรับใช้กับโครงสร้างพื้นฐานแบบไร้เซิร์ฟเวอร์หรือโครงสร้างพื้นฐาน PASS บางอย่าง (เช่น Heroku) คุณไม่สามารถคงข้อมูลบนระบบไฟล์ของเซิร์ฟเวอร์ได้ เนื่องจากอาจมีการเปลี่ยนแปลงในทุกคำขอ (แบบไร้เซิร์ฟเวอร์) หรือการปรับใช้ (PASS) หากต้องการคงข้อมูลไว้ คุณควรเก็บข้อมูลผู้ใช้ไว้ในฐานข้อมูลภายนอก Upstash Redis DB เป็นโซลูชันที่ยอดเยี่ยมในการจัดเก็บข้อมูลเซสชันด้วยเหตุผลดังต่อไปนี้:
- คล้ายกับ Redis Sessions โดยธรรมชาติแล้ว จะมี
key:value
โครงสร้างข้อมูลโดยที่คีย์คือรหัสของเซสชัน และค่าคือข้อมูลที่ต่อเนื่องกัน - Redis มีกลไกการหมดอายุในตัวซึ่งช่วยลดความจำเป็นในการล้างเซสชันที่หมดอายุ
- เซสชันอาจเก็บข้อมูลผู้ใช้ที่ละเอียดอ่อน และ Upstash Redis เข้ารหัสข้อมูลที่เก็บไว้ทั้งหมด
- Upstash ใช้ HTTP REST API อย่างง่าย HTTP เป็นวิธีที่ง่ายที่สุดในการสื่อสารจากโครงสร้างพื้นฐานแบบไร้เซิร์ฟเวอร์
วิธีใช้ Upstash เป็นผู้ให้บริการเซสชันใน Redis
โพสต์นี้ใช้พื้นที่เก็บข้อมูลเซสชัน Redis โดยใช้ตัวอย่าง Upstash ที่ฉันเขียน อย่าลังเลที่จะโคลน repo Remix แล้วลองใช้เลย
ขั้นตอนที่ 1 - รับคีย์ Upstash API ของคุณ
- ไปที่ https://upstash.com/ และสร้างบัญชีใหม่
- สร้างฐานข้อมูล Redis ใหม่
- คัดลอก
UPSTASH_REDIS_REST_URL
&UPSTASH_REDIS_REST_TOKEN
และเก็บไว้ในไฟล์ชื่อ.env
ในรูทของโปรเจ็กต์ Remix - ติดตั้ง
dotenv
-$ npm install --save-dev dotenv
- สิ่งนี้จะช่วยให้คุณฉีดตัวแปรสภาพแวดล้อมของคุณจาก.env
ไฟล์ที่คุณเพิ่งสร้างขึ้น - ไปหาคุณ
package.json
ไฟล์และแทนที่dev
รูปแบบสคริปต์remix dev
ถึงdotenv/config node_modules/.bin/remix dev
.
ขั้นตอนที่ 2 - ใช้งานหลัก createSessionStorage
เพื่อสร้างการใช้งานเซสชัน Upstash
Remix นำเสนอ API ที่ยอดเยี่ยมในการสร้างการรวมเซสชันของคุณเองโดยใช้ createSessionStorage
. ให้ใช้ฟังก์ชันนี้เพื่อรวม 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
Upstash API เพื่อโต้ตอบกับฐานข้อมูล Redis
สิ่งที่ควรทราบ:
- คุกกี้ที่ส่งผ่านจะมี
cookie expiration date
ในjs Date
รูปแบบ. เราใช้expiresToSeconds
เพื่อแปลงข้อมูลเป็นวินาทีตามที่ Redis คาดหวัง - เมื่อตั้งค่าคุกกี้ อย่าลืมกำหนดวันหมดอายุของคุกกี้ Redis จะลบเซสชันเหล่านั้นโดยอัตโนมัติเมื่อหมดอายุ
- เราใช้
crypto
เพื่อสร้างรหัสเซสชันที่ไม่ซ้ำกัน คุณสามารถใช้ทางเลือกอื่นเพื่อสร้างรหัสเฉพาะ ฉันเลือกตัวเลือกนี้เนื่องจากตัวเลือกนี้ถูกใช้ในคอร์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
. ฟังก์ชันเหล่านี้ช่วยให้แอปโต้ตอบกับเซสชันได้ นอกจากนี้เรายังได้สร้างคุกกี้เพื่อเก็บข้อมูลอ้างอิงถึงเซสชันในไคลเอนต์
ตั้งค่าระยะเวลาหมดอายุตามความต้องการทางธุรกิจของคุณ สำหรับข้อมูลเพิ่มเติม โปรดอ่าน https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
การใช้เซสชันในเส้นทาง Remix
การใช้ 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>;
}
ตัวอย่างนี้สาธิตวิธีจัดการกับสองสถานะที่เป็นไปได้ของเซสชันผู้ใช้ (ผู้ใช้มีเซสชันหรือผู้ใช้ไม่มีเซสชัน) หากผู้ใช้ไม่มีเซสชัน การนำทางไปยังไฟล์ดัชนีของแอปจะสร้างเซสชันใหม่และจัดเก็บข้อมูลจำลองบางส่วน หากผู้ใช้มีเซสชันที่ถูกต้อง (ไม่หมดอายุ) เส้นทางจะแสดงข้อมูลของเซสชัน
ขั้นตอนที่ 4 - ปรับใช้
เมื่อคุณใช้งานเซสชันโดยใช้ Upstash แล้ว คุณสามารถเลือกกลยุทธ์การปรับใช้ที่คุณเลือกได้
อย่าลืมตั้งค่าตัวแปรสภาพแวดล้อม Upstash ของคุณ
ภาคผนวก
การใช้ createFileSessionStorage
สำหรับการพัฒนาในพื้นที่และ createUpstashSessionStorage
ในการแสดงละคร / การผลิต
มีแนวโน้มว่าจะต้องการพัฒนาในขณะที่ออฟไลน์ เมื่อพัฒนาในเครื่อง คุณสามารถแทนที่ createUpstashSessionStorage
ด้วย createFileSessionStorage
โดยการตรวจจับ NODE_ENV
current ปัจจุบัน .
หลังจากทดสอบว่าการใช้งาน 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
บทสรุป
ในโพสต์นี้ เราเห็นวิธีใช้ Upstash Redis DB เพื่อโฮสต์ข้อมูลการจัดเก็บเซสชันของเรา Remix API สรุปการใช้งานพื้นที่จัดเก็บเซสชันเฉพาะได้ดีมาก ทำให้การผสานรวมเป็นไปอย่างคับแคบ หากคุณต้องการเล่นกับตัวอย่าง คุณสามารถตรวจสอบได้ในซอร์สโค้ด Remix ที่ https://github.com/remix-run/remix/tree/main/examples/redis-upstash-session
เพลิดเพลิน