什麼是 supabase#
supabase 是一個替代 Firebase 的開源 BaaS 專案。其提供了各種現代應用所需的穩定、強大、易於使用和可擴展的後端功能。Supabase 基於 PostgreSQL 資料庫和 RESTful API 構建,並提供身份驗證、實時數據推送、存儲和其他一些常見的後端服務。
不需要買伺服器,只需掌握簡單的 SQL 語句和資料庫知識就可以創建一個後端服務。當然它的功能是非常強大的,這篇文章只介紹如何在 Next.js 中使用。
使用 supabase#
學習任務內容都需要詳細的閱讀官方文件
根據官方文件 Use Supabase with NextJS 這一節的內容,使用步驟分為如下幾步
這裡我使用 supabase 存儲部落格的閱讀量
創建專案並建表建資料#
通過 https://app.supabase.com/projects 創建一個專案
通過 SQL 編輯器或圖形介面 DataBase 創建一個表名為 Views
這裡通過圖形介面創建,在 Database 中使用右上角的 New table 創建 Views 表
列中的 slug 表示部落格的 title,count 表示對應部落格的訪問量
創建 Next.js 專案#
npx create-next-app@latest --typescript
安裝 supabase-js#
npm install @supabase/supabase-js
創建 supabase#
在根目錄下創建 lib 資料夾,創建一個名為 supabase.ts 的檔案
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL as string;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_KEY as string;
export const supabase = createClient(supabaseUrl, supabaseKey);
project_url 和 supabase_key 可以在專案的設定選項中找到
同樣不建議將 key 暴露出去,可以存在 env.local 中
💡 tips: 在 Next.js 中使用 env.local,需要加上 NEXT_PUBLIC 前綴,否則會報錯。
CRUD#
詳細的命令可以通過 JavaScript 文件查詢
當打開部落格文章頁面時,需要查詢當前部落格的閱讀量,可以使用
fetch(`/api/views`);
在 pages/api/views 目錄下創建 index.ts
import { supabase } from '@/lib/supabase';
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
let { data } = await supabase.from('Views').select('*');
return res.status(200).json(data);
} catch (e: any) {
console.log(e);
return res.status(500).json({ message: e.message });
}
}
通過寫類似於 sql 語句,可以從 Views 表中獲取全部的資料
也可以通過 post 傳參將 slug 傳進來,查詢對應的資料
同時當打開部落格文章頁面時,也需要對當前部落格的閱讀量加一,就可以用過 post 請求將 slug 參數傳入
fetch(`/api/views/${slug}`, {
method: 'POST'
});
在 pages/api/views 目錄下創建 [slug].ts
import { supabase } from '@/lib/supabase';
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
try {
const slug = req.query?.slug as string;
if (!slug) {
return res.status(400).json({ message: 'Slug is required.' });
}
const { data } = await supabase
.from('Views')
.select('count')
.eq('slug', slug);
const views = !data?.length ? 0 : Number(data[0].count);
if (req.method === 'POST') {
if (views === 0) {
await supabase.from('Views').insert({ count: views + 1, slug: slug });
return res.status(200).json({
total: views + 1
});
} else {
await supabase
.from('views')
.update({ count: views + 1 })
.eq('slug', slug);
return res.status(200).json({
total: views + 1
});
}
}
if (req.method === 'GET') {
return res.status(200).json({ total: views });
}
} catch (e: any) {
console.log(e);
return res.status(500).json({ message: e.message });
}
}
新建使用 insert,更新使用 update。這樣就可以將閱讀量存儲到 supabase 中
其他功能#
同時 supabase 也支持 bucket 存儲功能。我的專案中將 og image 存儲在 supabase 中
準備後面的專案中繼續使用 supabase,替代 Firebase。