Kakeru先生、Hasshi先生和其他人正在使用Supabase進行一些有趣的開發。與我們迄今為止所看到的瀑布式開發不同,我聽到了各種關於從UI定義功能需求的說法,但我無法讓自己被超越!
因此,這次我將創建一個簡單的備忘錄應用程序,並總結連接 Supabase 和 Prisma 並將資料作為備忘錄保存在資料庫中的步驟。Gemini CLI我也要用!
環境:Next.js
我們不會使用 Supabase 的 Auth、Realtime 或 RLS,而是使用 Prisima 透過 API 存取資料庫功能。由於資料庫表可以像 Javascript/Typescript 物件一樣處理,我們認為前端工程師可以輕鬆編寫他們熟悉的程式碼。
Prisma
Prisma ORM 是一個可與 TypeScript 和 JavaScript 一起使用的 ORM(物件關聯映射)函式庫。
簡單來說,它是一種讓你不用寫SQL,而是使用程式語言的物件中定義的方法,來操作資料庫的工具。
此外,Prisma 會自動從資料庫模式產生類型,因此如果您嘗試操作資料庫中不存在的列或錯誤類型的數據,您將收到編譯錯誤通知!
Supabase
Supabase 是一種全端後端服務,作為開源 Firebase 的替代品,其吸引力越來越大。
- 基於 PostgreSQL 資料庫,具有高度可擴展性和可靠性
- 即時資料庫功能會自動通知您資料變化
- 支援多種身份驗證方法(電子郵件/密碼、社交登入、電話身份驗證等)
- 文件儲存功能,高效率管理大文件
- 透過自動產生 RESTful 和 GraphQL API 實現快速開發
- 豐富的開發工具和 SDK 讓設定和部署變得簡單
我想強調一下連接到 Supabase 的步驟,Gemini CLI這是一款超方便的產品,簡直讓人想哭!我公司用的是 Google Workspace,太開心了!

我想使用 Supabase 和 Prisma 建立一個備忘錄功能。首先,建立 page.tsx。


好的,那麼,我想進行設置,以便當我按下「儲存備忘錄」按鈕時,我在文字區域中輸入的內容將會新增到「您的備忘錄」清單中。

看起來就像這樣,一切正常!您輸入的內容現在將會加入到下面的清單中。但是,由於這只是一個 JavaScript 事件,因此如果您重新加載,列表將會消失。
我們使用資料庫來儲存您的輸入!
首先,在Supabase端建立一個新專案。
使用“新建專案”按鈕建立一個新專案。請記下資料庫密碼,因為連接 Prisma 時需要用到它。

接下來,連接 Prisma。
npm install prisma --save-dev
npx prisma init
輸入這些命令將安裝 Prisma 並建立 Prisma 資料夾。
將 .env 檔案中的 DATABASE_URL 替換為 Supabase 連線 URL。將 [YOUR-PASSWORD] 替換為您在 Supabase 中設定的資料庫密碼。
DATABASE_URL="postgresql://postgres.odoaingwnxkhkeujwhtp:[YOUR-PASSWORD]@aws-1-ap-northeast-1.pooler.supabase.com:5432/postgres"
然後/prisma/schema.prisma
模式(資料庫結構定義)以 編寫。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Memo {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
}
○○型號可以隨意命名。
一旦編寫了模式,就可以遷移它。
npx prisma migrate dev --name init
將會產生一個migration.sql文件,並在Supabase端建立一個資料表。
建立連接到 Supabase 的 API
建立一個連線API,將輸入的值儲存到Supabase。
在您的專案中安裝 Prisma Client。
npm install @prisma/client
連接到 Supabase
/libs/prisma.ts
import { PrismaClient } from "@prisma/client";
const Prisma = new PrismaClient(); //インスタンス化
export const main = async () => {
try {
await Prisma.$connect();
} catch (error) {
return Error("DB接続に失敗しました");
}
};
API
/api/memos/route.ts
import { NextResponse } from "next/server";
import { prisma } from '@/lib/prisma';
export const GET = async (req: Request, res: NextResponse) => {
try {
await main();
const memos = await Prisma.memo.findMany();
return NextResponse.json(memos);
} catch (error) {
return NextResponse.json("エラーが発生しました");
} finally {
await Prisma.$disconnect();
}
};
export const POST = async (req: Request, res: NextResponse) => {
const { content } = await req.json();
try {
await main();
const memos = await Prisma.memo.**create**({
data: {
content: content,
},
});
return NextResponse.json(memos);
} catch (error) {
return NextResponse.json("エラーが発生しました");
} finally {
await Prisma.$disconnect();
}
};
GET 函數是從資料庫中檢索所有記錄的 API,findMany() 方法檢索所有符合條件的記錄。 Prisma.memo.findMany() 中的「memo」是模式名稱。
POST 函數是一種向資料庫新增資料的 API,使用 create() 建立。
另外,還有delete、update等方法,即使無法寫SQL語句,也可以像JavaScript一樣做。
到這裡,一切就緒了。
您所要做的就是將您之前編寫的 API 帶入 page.tsx 並將其合併。
'use client';
import React, { useState, useEffect } from 'react';
interface Memo {
id: number;
content: string;
createdAt: string;
}
export default function MemoApp() {
const [memos, setMemos] = useState<Memo[]>([]);
const [newMemo, setNewMemo] = useState('');
const fetchMemos = async () => {
const response = await fetch('/api/memos');
const data = await response.json();
setMemos(data);
};
useEffect(() => {
fetchMemos();
}, []);
const handleSaveMemo = async (e: React.FormEvent) => {
e.preventDefault();
if (newMemo.trim() !== '') {
await fetch('/api/memos', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: newMemo }),
});
setNewMemo('');
fetchMemos();
}
};
return (
<div className="bg-white min-h-screen">
<div className="max-w-2xl mx-auto px-4 py-16">
<header className="text-center mb-12">
<h1 className="text-5xl font-extrabold text-gray-900">Memo</h1>
</header>
<main>
<div className="mb-12">
<form onSubmit={handleSaveMemo}>
<textarea
className="w-full p-4 text-gray-800 bg-gray-100 rounded-lg border-2 border-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent transition"
placeholder="Create a new memo..."
rows={3}
value={newMemo}
onChange={(e) => setNewMemo(e.target.value)}
></textarea>
<div className="flex justify-end mt-4">
<button
type="submit"
className="px-6 py-2 bg-gray-800 text-white font-semibold rounded-lg hover:bg-gray-900 transition"
>
Save Memo
</button>
</div>
</form>
</div>
<section>
<h2 className="text-3xl font-bold text-gray-800 mb-6">Your Memos</h2>
<div className="space-y-4">
{memos.length > 0 ? (
memos.map((memo) => (
<div key={memo.id} className="bg-gray-50 p-6 rounded-lg shadow-sm">
<p className="text-gray-700">{memo.content}</p>
</div>
))
) : (
<div className="text-center text-gray-500">
<p>No memos yet. Add one above!</p>
</div>
)}
</div>
</section>
</main>
</div>
</div>
);
}


它保存在 Supabase 端!
這次,我依靠 Gemini 創建了一個粗略的輪廓,但如果我可以使用資料庫來保存值,那麼我可以創建的功能和應用程式的範圍將會更廣泛!
我先入為主地認為後端會很難,但能夠使用 GUI 工具管理資料庫很容易理解,並且降低了資料庫整合的門檻!
耶!
我使用 JavaScript、React 和 Next.js 開發前端項目,專注於標記語言。當我參與開發的網站成功發佈時,我感到無比欣慰!我的嗜好是彈吉他。我既喜歡寫程式碼,也喜歡玩程式碼!
Hiratchi
前端工程師 / 2022年入職