Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

SvelteKitとUpstash Redisで構築するTODOアプリの作り方

この記事では、SvelteKitUpstashが提供するサーバーレスRedisを組み合わせて、シンプルなTODOアプリを構築する手順を解説します。

SvelteKitは、あらゆる規模のWebアプリケーションを構築できるフレームワークです。快適な開発体験と、ファイルシステムベースの柔軟なルーティングが大きな魅力です。

プロジェクトの作成

まずは以下のコマンドでプロジェクトを新規作成します。

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

SvelteKitとUpstash Redisで構築するTODOアプリの作り方

プロジェクトの雛形ができたら、依存パッケージをインストールし、開発サーバーを起動しましょう。

npm install
npm run dev

SvelteKitとUpstash Redisで構築するTODOアプリの作り方

ユーザーインターフェースの作成

ここでは、TODOアイテムを入力するためのシンプルなフォームと、タスクを一覧表示するリストを作成します。現時点ではダミーデータを表示していますが、後ほどデータベースと連携させます。

// 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>

ここまで実装すると、ブラウザ上で次のような画面が確認できます。

SvelteKitとUpstash Redisで構築するTODOアプリの作り方

データベースの準備

データはUpstash Redisに保存します。まずUpstashでデータベースを作成しましょう。今回は、サーバーレス環境との相性に優れたHTTPベースのUpstashクライアントを使用します。

npm install @upstash/redis

次に、Upstashコンソール上でRedisデータベースを作成し、発行されたUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKENを.envファイルにコピー&ペーストします。

UPSTASH_REDIS_REST_URL=https://global-renewing-gecko-31543.upstash.io
UPSTASH_REDIS_REST_TOKEN=AXs3ACsjfg684jJBFQgN34je7RFJ58wYjg4NjMt=

環境変数を読み込むためにdotenvもインストールしておきましょう。

npm install dotenv

続いてlib/redis.tsを作成し、以下のようにRedisインスタンスを初期化します。

// 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;

APIの作成

SvelteKitでは、ルートフォルダ内のjs/tsファイルがAPIバックエンドとして機能します。つまり、index.svelteがフロントエンド、index.tsがバックエンドという役割分担になります。

それではindex.tsを作成し、必要なAPIメソッドを追加していきましょう。

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

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

export const get: RequestHandler = async () => {
  // ページが読み込まれるたびに実行される
  return { body: { todos: [] } };
};

export const post: RequestHandler = async ({ request }) => {
  // フォーム: TODOの作成
  return redirect;
};

export const patch: RequestHandler = async ({ request }) => {
  // フォーム: TODOの更新
  return redirect;
};

export const del: RequestHandler = async ({ request }) => {
  // フォーム: TODOの削除
  return redirect;
};

POST:TODOアイテムの作成

まずはTODOアイテムの登録処理を実装します。

// src/routes/index.ts
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;
};

GET:TODOアイテムの一覧取得

続いて、保存済みのTODOアイテムを一覧表示する処理です。

// src/routes/index.ts
export const get: RequestHandler = async () => {
  let todos = [];

  const data = await redis.hgetall(databaseName);
  if (!data) return { body: { todos } };

  // データを正規化
  todos = Object.keys(data)
    .map((key) => ({
      id: key,
      text: data[key]["text"],
      status: data[key]["status"],
    }))
    // id = タイムスタンプ
    .sort((a, b) => parseInt(b.id) - parseInt(a.id));

  return { body: { todos } };
};

記事をシンプルに保つため、ここでは「タスクの削除」と「完了状態の切り替え」のコードは省略していますが、GitHubリポジトリで全文を確認できます。

これですべての準備が整いました!

ソースコード | デモアプリ

今後は同じTODOアプリをNext.jsでも実装し、両フレームワークの開発体験を比較する予定です。

最新情報はTwitterやDiscordで発信していますので、ぜひフォローしてください。

  1. Cloudflare WorkersとRedisで実現するエッジコンピューティング活用術

    エッジコンピューティングは、近年もっとも注目されている技術のひとつです。CDNがファイルをユーザーの近くに配置できるようにしたのと同じように、エッジコンピューティングはアプリケーションそのものをユーザーの近くで実行できるようにします。これにより、開発者はグローバルに分散され、高いパフォーマンスを発揮するアプリケーションを構築できるようになります。 Cloudflare Workersとステートレス性の課題 現在この分野をリードしている製品がCloudflare Workersです。コールドスタートのないサーバーレス実行環境を提供し、Cloudflareのグローバルネットワークを活かすことで、ア

  2. Redis GEORADIUSBYMEMBERコマンドの使い方を実例付きで解説 – Redisチュートリアル

    このチュートリアルでは、Redisに保存された地理空間データ(ジオスペーシャル値)の中から、特定の範囲内に含まれる要素を取得する方法を学びます。そのために使用するのが GEORADIUSBYMEMBER コマンドです。 GEORADIUSBYMEMBERコマンドとは GEORADIUSBYMEMBERコマンドは、キーに保存された地理空間値(ソート済みセット)のメンバーのうち、指定したメンバーの経度・緯度と半径の引数から算出される円形エリアの境界内にある1つ以上のメンバーを返すために使用します。このエリアは、指定したメンバーの経度・緯度を円の中心位置とし、指定した単位による半径を円の半径として計