Skip to Content
LaunchExt | Chrome 扩展开发平台 (Next.js + Plasmo) 🚀 Read more → 
文档Supabase 集成指南

使用 Supabase 快速开始

介绍

Supabase 是一个开源的 Firebase 替代品。

这个快速入门是一个简单的示例,展示如何在 Plasmo 中使用 Supabase。

先决条件

使用 Supabase 初始化 Plasmo 项目

pnpm create plasmo --with-supabase

设置环境变量

为了使 Supabase 工作,我们需要定义 URL 和 KEY。

您可以在 Supabase 项目仪表板中找到这些:

让我们在 .env 文件中添加它们:

.env
PLASMO_PUBLIC_SUPABASE_URL="请更改我" PLASMO_PUBLIC_SUPABASE_KEY="请更改我"

Supabase 存储

我们需要初始化 Supabase,所以让我们添加一个名为 core/supabase.ts 的文件:

core/supabase.ts
import { createClient } from "@supabase/supabase-js" import { Storage } from "@plasmohq/storage" const storage = new Storage({ area: "local" }) export const supabase = createClient( process.env.PLASMO_PUBLIC_SUPABASE_URL, process.env.PLASMO_PUBLIC_SUPABASE_KEY, { auth: { storage, autoRefreshToken: true, persistSession: true, detectSessionInUrl: true } } )

添加重定向 URL

当用户注册时,他们需要确认他们的电子邮件。为此,我们需要向我们的 Supabase 项目添加一个重定向 URL。

首先,我们需要为我们的扩展创建一个一致的 ID 用于开发。当您推送到不同的 Web 商店时,您会得到不同的 ID。要了解更多关于这一切如何工作的信息,请查看我们关于为 Chrome 扩展创建一致 ID  的博客文章

转到 Itero KeyPair 工具  生成您的一致扩展 ID。

我们可以将 ID 和公钥存储在 .env 文件中:

.env
CRX_ID="用 Itero KeyPair 工具中的 CRX ID 值替换" CRX_KEY="用 Itero KeyPair 工具中的公钥值替换"

然后,在 package.json 的 manifest.key 值中引用公钥:

"manifest": { "host_permissions": [ "https://*/*" ], "key": "$CRX_KEY", }

现在我们需要确保浏览器不会阻止对我们的选项页面的访问。为此,我们必须将其添加到清单中的 web_accessible_resources 中:

"web_accessible_resources": [ { "resources": [ "options.html" ], "matches": [ "<all_urls>" ], "extension_ids": [ "$CRX_ID" ] } ]

转到 Supabase 控制台,点击”认证”选项卡,然后点击 URL 配置。

现在在您的站点 URL 以及重定向 URL 中添加以下 URL:

chrome-extension://<CRX_ID>/options.html

CRX_ID 替换为 Itero KeyPairs 工具生成的扩展 ID,或生产 Web 商店给您的实际 ID。

与 React 组件集成

现在我们可以在 React 组件中编写使用 Supabase 的代码!

以下是在扩展选项页面的 React 组件中使用 Supabase 的示例。

options.tsx
import type { Provider, User } from "@supabase/supabase-js" import { useEffect, useState } from "react" import { Storage } from "@plasmohq/storage" import { useStorage } from "@plasmohq/storage/hook" import { supabase } from "~core/supabase" function IndexOptions() { const [user, setUser] = useStorage<User>({ key: "user", instance: new Storage({ area: "local" }) }) const [username, setUsername] = useState("") const [password, setPassword] = useState("") useEffect(() => { async function init() { const { data, error } = await supabase.auth.getSession() if (error) { console.error(error) return } if (!!data.session) { setUser(data.session.user) } } init() }, []) const handleEmailLogin = async ( type: "LOGIN" | "SIGNUP", username: string, password: string ) => { try { const { error, data: { user } } = type === "LOGIN" ? await supabase.auth.signInWithPassword({ email: username, password }) : await supabase.auth.signUp({ email: username, password }) if (error) { alert("认证错误: " + error.message) } else if (!user) { alert("注册成功,确认邮件应该很快发送!") } else { setUser(user) } } catch (error) { console.log("错误", error) alert(error.error_description || error) } } const handleOAuthLogin = async (provider: Provider, scopes = "email") => { await supabase.auth.signInWithOAuth({ provider, options: { scopes, redirectTo: location.href } }) } return ( <main style={{ display: "flex", justifyContent: "center", alignItems: "center", width: "100%", top: 240, position: "relative" }}> <div style={{ display: "flex", flexDirection: "column", width: 240, justifyContent: "space-between", gap: 4.2 }}> {user && ( <> <h3> {user.email} - {user.id} </h3> <button onClick={() => { supabase.auth.signOut() setUser(null) }}> 退出登录 </button> </> )} {!user && ( <> <label>邮箱</label> <input type="text" placeholder="您的用户名" value={username} onChange={(e) => setUsername(e.target.value)} /> <label>密码</label> <input type="password" placeholder="您的密码" value={password} onChange={(e) => setPassword(e.target.value)} /> <button onClick={(e) => { handleEmailLogin("SIGNUP", username, password) }}> 注册 </button> <button onClick={(e) => { handleEmailLogin("LOGIN", username, password) }}> 登录 </button> <button onClick={(e) => { handleOAuthLogin("github") }}> 使用 GitHub 登录 </button> </> )} </div> </main> ) } export default IndexOptions

完整示例

要查看完整示例,请查看我们示例仓库中的 with-supabase 

最后更新于