Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

สร้างแอป TODO รวดเร็วด้วย SvelteKit และ Serverless Redis (Upstash)

ในบทความนี้ เราจะสร้างแอปพลิเคชัน TODO แบบง่ายๆ โดยใช้ SvelteKit ร่วมกับ Serverless Redis (Upstash) เพื่อให้ได้แอปที่รวดเร็ว สามารถขยายตัวได้ และเหมาะสำหรับสภาพแวดล้อม Serverless

SvelteKit เป็นเฟรมเวิร์กสำหรับสร้างแอปพลิเคชันเว็บทุกขนาด พร้อมประสบการณ์การพัฒนาที่ยอดเยี่ยม และระบบ Routing แบบ Filesystem ที่ยืดหยุ่น

1. สร้างโปรเจกต์

รันคำสั่งด้านล่างเพื่อสร้างโปรเจกต์ SvelteKit ใหม่:

npm init svelte@next todo-app-with-redis

ตอบคำถามการตั้งค่าตามที่ต้องการ (เลือก TypeScript, ESLint, Prettier เป็นต้น) จากนั้นติดตั้ง Dependencies และรันเซิร์ฟเวอร์พัฒนา:

npm install
npm run dev

เปิดเบราว์เซอร์ที่ https://localhost:5173 คุณจะเห็นหน้าแรกของ SvelteKit

2. สร้าง User Interface

เราจะสร้างฟอร์มเพิ่ม TODO และรายการแสดงผล โดยแบ่งเป็น 2 ส่วน: งานที่ยังไม่เสร็จ และงานที่เสร็จแล้ว

ไฟล์ src/routes/index.svelte

<script lang="ts">
  import type { Todo } from "../lib/types";
  import TodoItem from "../components/Todo.svelte";

  export let todos: Todo[] = [
    { id: '1', text: 'Create database', status: true },
    { id: '2', text: 'Copy database url', status: false }
  ];

  const uncheckedTodos = todos.filter((todo) => !todo.status);
  const checkedTodos = todos.filter((todo) => todo.status);
</script>

<main class="container">
  <form class="new" action="/" method="post">
    <input
      type="text"
      name="text"
      autofocus
      aria-label="Add todo"
      class="input"
      placeholder="What needs to be done?"
    />
  </form>

  {#if uncheckedTodos.length}
    <div class="todos">
      {#each uncheckedTodos as todo (todo.id)}
        <TodoItem {todo} />
      {/each}
    </div>
  {/if}

  {#if checkedTodos.length}
    <div class="todos todos-done">
      {#each checkedTodos as todo (todo.id)}
        <TodoItem {todo} />
      {/each}
    </div>
  {/if}
</main>

คอมโพเนนต์ TODO (src/components/Todo.svelte)

<script lang="ts">
  import type { Todo } from "../lib/types";
  export let todo: Todo;
</script>

<div class="todo">
  <form action="/?_method=PATCH" method="post">
    <input type="hidden" name="todo" value={JSON.stringify(todo)} />
    <button
      class="checkbox"
      aria-label="Mark todo as {todo.status ? 'not done' : 'done'}"
    >
      {todo.status ? "✓" : ""}
    </button>
  </form>
  <span class="text">{todo.text}</span>
  <form action="/?_method=DELETE" method="post">
    <input type="hidden" name="id" value={todo.id} />
    <button class="delete" aria-label="Delete todo">✕</button>
  </form>
</div>

3. เตรียมฐานข้อมูล Upstash Redis

เราจะใช้ Upstash Redis ซึ่งเป็น Redis แบบ Serverless ที่เข้าถึงผ่าน HTTP REST API เหมาะสำหรับ Edge/Serverless Functions

  1. สร้างฐานข้อมูลที่ Upstash Console
  2. คัดลอก UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN
  3. ติดตั้งแพ็กเกจที่จำเป็น:
npm install @upstash/redis dotenv

สร้างไฟล์ src/lib/redis.ts

// src/lib/redis.ts
import "dotenv/config";
import { Redis } from "@upstash/redis";

export const databaseName = process.env.NODE_ENV === "development"
  ? "redis-with-svelte-kit-dev"
  : "redis-with-svelte-kit";

const redis = new Redis({
  url: process.env.UPSTASH_REDIS_REST_URL,
  token: process.env.UPSTASH_REDIS_REST_TOKEN,
});

export default redis;

สร้างไฟล์ .env ในรูทโปรเจกต์และใส่ค่าที่ได้จาก Upstash Console:

UPSTASH_REDIS_REST_URL=https://your-database.upstash.io
UPSTASH_REDIS_REST_TOKEN=your-token-here

4. สร้าง API Endpoints

ใน SvelteKit ไฟล์ +page.svelte เป็น Frontend ส่วน +page.server.ts (หรือ index.ts ในเวอร์ชันเก่า) จะเป็น Backend API

ไฟล์ src/routes/index.ts

// src/routes/index.ts
import redis, { databaseName } from "../lib/redis";
import type { RequestHandler } from "@sveltejs/kit";

const redirect = {
  status: 303,
  headers: { location: "/" },
};

// GET - โหลดรายการ TODO ทั้งหมด
export const get: RequestHandler = async () => {
  let todos: any[] = [];
  const data = await redis.hgetall(databaseName);

  if (!data) return { body: { todos } };

  // Normalize และจัดเรียงตาม ID (timestamp) ใหม่สุดก่อน
  todos = Object.keys(data)
    .map((key) => ({
      id: key,
      text: data[key]["text"],
      status: data[key]["status"],
    }))
    .sort((a, b) => parseInt(b.id) - parseInt(a.id));

  return { body: { todos } };
};

// POST - สร้าง TODO ใหม่
export const post: RequestHandler = async ({ request }) => {
  const form = await request.formData();
  const text = form.get("text");
  const id = Date.now().toString();
  const todo = JSON.stringify({ text, status: false });

  await redis.hset(databaseName, id, todo);
  return redirect;
};

// PATCH - อัปเดตสถานะ TODO
export const patch: RequestHandler = async ({ request }) => {
  const form = await request.formData();
  const todoStr = form.get("todo");
  const { id, text, status } = JSON.parse(todoStr as string);

  await redis.hset(databaseName, { [id]: { text, status: !status } });
  return redirect;
};

// DELETE - ลบ TODO
export const del: RequestHandler = async ({ request }) => {
  const form = await request.formData();
  const id = form.get("id");
  await redis.hdel(databaseName, id as string);
  return redirect;
};

5. สรุปและทดสอบ

ตอนนี้แอป TODO ของคุณพร้อมใช้งานแล้ว! ลองรัน npm run dev และทดสอบการเพิ่ม แก้ไข ลบ และติ๊กสถานะงาน

โค้ดต้นฉบับ: GitHub Repository
Demo App: Live Demo

ขอบคุณที่อ่านครับ! ติดตามบทความต่อไปที่จะเปรียบเทียบกับ Next.js และ Remix นะครับ