banner
xiaole

xiaole

前端工程师 | Trying To Do Better
tg_channel
twitter
github
email

如何在 Next.js 專案中使用 supabase

什麼是 supabase#

supabase 是一個替代 Firebase 的開源 BaaS 專案。其提供了各種現代應用所需的穩定、強大、易於使用和可擴展的後端功能。Supabase 基於 PostgreSQL 資料庫和 RESTful API 構建,並提供身份驗證、實時數據推送、存儲和其他一些常見的後端服務。

不需要買伺服器,只需掌握簡單的 SQL 語句和資料庫知識就可以創建一個後端服務。當然它的功能是非常強大的,這篇文章只介紹如何在 Next.js 中使用。

使用 supabase#

學習任務內容都需要詳細的閱讀官方文件

根據官方文件 Use Supabase with NextJS 這一節的內容,使用步驟分為如下幾步

這裡我使用 supabase 存儲部落格的閱讀量

創建專案並建表建資料#

通過 https://app.supabase.com/projects 創建一個專案

new project

通過 SQL 編輯器或圖形介面 DataBase 創建一個表名為 Views

database

這裡通過圖形介面創建,在 Database 中使用右上角的 New table 創建 Views 表

create table

列中的 slug 表示部落格的 title,count 表示對應部落格的訪問量

創建 Next.js 專案#

npx create-next-app@latest --typescript

image.png

安裝 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 可以在專案的設定選項中找到

image.png

同樣不建議將 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 中

image.png

準備後面的專案中繼續使用 supabase,替代 Firebase。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。