视频版:https://www.bilibili.com/video/BV1ZJsBznEt3
2025年最火的后端开源项目那必须是Supabase。Supabase是一个开源的后端级服务框架,在强大的PostgreSQL数据库的基础上,封装了用户认证、文件存储、可视化的运维面板等功能,为开发者提供了一整套开箱即用的后端基础设施。Supabase在Github上面有恐怖的9万star,这已经是整个Github上面最顶级的开源项目之一了。
总的来说,Supabase为开发者提供了三大部分的能力:后端、前端与免费的云服务。Supabase在后端提供数据库、文件存储、边缘函数、用户鉴权等各种基础设施。在前端方面,Supabase提供客户端SDK,可以将任何一个前端框架,比如React, Vue,甚至手机APP,用几行代码就可以轻松接入后端。
Supabase是一个完全开源免费的项目,我们可以使用源代码或者docker镜像,自己部署一个Supabase的完整实例。如果懒得自己部署,Supabase的官方还提供一个云服务的版本,我们只需要注册一个账户,就能立即获得一个免费的Supabase实例。

Supabase开箱即用的方便特性,跟AI编程是绝配,配合AI编程,可以超级快速搭建一个带用户鉴权、加数据库的前后端的完整应用。
本期视频是一个关于Supabase的完整教程,我准备从数据库核心、Supabase SDK、RLS行级安全策略、还有自部署这几个方面来全面介绍Supabase的使用。Supabase的基础是一个完整的PostgreSQL数据库,它具备postgres的一切功能。我们先从最简单易用的云服务版本开始上手,视频的最后,我会介绍如何进行本地部署。
数据库核心
我们来到Supabase的官网supabase.com,右上角点击sign in。这里我选择用Github登录。

登录完成以后创建一个组织,这里填上我的名字:技术爬爬虾,plan这里选择免费的,创建。

然后下一步创建一个项目,也就是一个数据库实例,填写一个密码。区域这里我选择新加坡,

开始,这样我们就拥有了一个postgres数据库的完整实例。
在左侧Table Editor,

create table可以创建数据库表,这里可以添加字段表。创建出来可以编辑新增一条记录,填写好数据,点击保存。在这个UI界面,还可以对数据进行编辑,删除等等。左侧找到SQL Editor,

会打开一个SQL语句的编辑窗口,我们可以在这里面直接编写SQL语句,点击右下角的run就可以执行。
我们在左侧菜单找到Database,

这里有postgres的所有的基础功能:schema, 表, 函数, 触发器, 枚举, 插件, 索引。publications是一个实时监控,可以把表的修改信息以Websocket的形式推送出去,这个我们等下再看。我之前有两期完整视频,详细介绍过postgres这个数据库,还有它的一些进阶使用技巧,数据库的基础功能我就不再赘述了。
视频:
https://www.bilibili.com/video/BV1FHHyzYEbA/?vd_source=c1b591bb896c1b265c7f5358017dcd77
https://www.bilibili.com/video/BV1FUYQz7E4H/?vd_source=c1b591bb896c1b265c7f5358017dcd77

我们来看一个重要部分,叫做插件(Extensions)。现代Web开发中,各种花哨的工具层出不穷,其实一个PostgreSQL数据库搭配上插件,就能存下世间万物,可以很大程度上代替这些花哨的工具。
这里我们看一个例子postgis。

安装这个插件,postgres就有了存储地理位置信息的能力,可以把postgres变成一个性能顶尖的企业级地理信息系统数据库。我们在右边把这个开关开起来,这里需要选择一个schema去应用这个扩展,我选择public,这样就开启成功了,比我们之前视频里讲的需要从服务器里面安装对应的软件包,就简单太多了。
我来创建一个表,用来存储城市里面的地理位置信息,GEOMETRY是插件提供的一个自定义类型,用来存储地理位置信息。
CREATE TABLE city_map (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
-- 4326 是GPS坐标系统的代号
geom GEOMETRY(GEOMETRY, 4326)
);
往表里插入三个地理位置相关的测试数据:一个四边形的公园,一条直线型的河流,还有一个坐标点。
INSERT INTO city_map (name, geom) VALUES
(
'人民公园',
-- 一个四边形的公园
ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))', 4326)
),
(
'护城河',
-- 一条折线形的河流
ST_GeomFromText('LINESTRING(-5 5, 15 5)', 4326)
),
(
'电话亭',
-- 一个点坐标
ST_GeomFromText('POINT(12 8)', 4326)
);
我们可以使用插件提供的函数来计算人民公园的面积,使用插件提供的操作符来计算两个地理位置之间的距离。这条SQL语句的意思是查找三个距离电话亭最近的地理元素。
SELECT name, ST_Area(geom)
FROM city_map
WHERE name = '人民公园';
数据库连接
除了在网页上操作这个postgres数据库,Supabase还提供了远程连接的方式。我们点击上面的connect按钮,

这里Supabase为我们提供了一个远程连接的地址,

我们可以把它接入到任意一个数据库的客户端,或者Java Python之类的后台代码里面。我用我的数据库工具DBeaver来连接一下:
新建数据库连接-->选择postgres,主机我们填写这一串,端口5432,数据库名与用户名都不用改,密码填写我们创建Supabase项目时候的密码,点击完成。

这样,我们就把Supabase的数据库连接进了客户端工具。这里注意一下,选择Direct Connection,也就是直连模式,它是不支持IPV4的。如果你的网络只能用IPV4的话,需要选择最下面这个Session pooler。Session Pooler跟直连模式非常的像,好处是它支持IPV4。

在连接模式里面,中间还有一个Transaction pooler,这个是supabase的连接池模式。在直连模式下面,需要后端服务自己维护连接池,比如用springboot的Hikari。
而连接池模式下面,supabase会自动为我们维护连接池,从而显著降低数据库连接的压力,特别适合一些无状态服务,比如无服务器函数或者边缘函数,他们都是按需启动,不用时就销毁,没有能力长时间维护一个连接池,这时候就应该选择transaction pooler模式,让supabase来负责维护连接池。
Supabase SDK
以上就是Supabase作为一个数据库的功能,我们来看下一部分Supabase SDK。Supabase SDK可以将任何一个前端框架,比如React Vue甚至手机APP,用一行代码就接入后端。Supabase SDK一般是配合这里的鉴权功能来使用的。我们回到项目的首页,在最下面,这里有一段Javascript代码,这就是最基础的SDK的使用。

我们来创建一个前端项目试一下。之前爬爬虾的视频老是用Nextjs,估计大家已经看烦了,这里我们换一个热门的前端框架,就是VUE。
打开一个文件夹,右键在终端打开,进行前端开发。电脑上需要先安装node.js,执行第一个命令初始化一个Vue工程。项目初始化完成以后,我们根据这里的提示再来操作一下

cd vue-project
npm install
npm run dev
这样一个VUE工程就创建好了,我们进入以后就可以看到它的代码。

接下来,我们把Supabase的SDK接入这个前端工程,第一步就是把Supabase的SDK在工程里面安装一下,才能import进来。
npm install @supabase/supabase-js
我们找一段能写TS代码的地方,把这个SDK来测试一下。这里我App.vue这个文件为例,我把官网上的示例代码粘贴过来。这里的Supabase API Key我直接把官网上面粘贴过来。
const supabaseUrl = 'https://sqttzihmuyigautyhyzd.supabase.co'
const supabaseKey = "官网的API Key"
const supabase = createClient(supabaseUrl, supabaseKey);
await supabase.auth.signUp({
email: 'tech-shrimp@outlook.com',
password: 'Supabase123!'
})
这里有的观众朋友们可能会好奇,你把API Key直接写到前端代码里面,这个API Key不就直接泄露了吗?难道这样做不是违反安全规范吗?我们来到Supabase的官网,来看一下这段话:

这里说这个key在浏览器里面使用是安全的,如果你启用了RLS,也就是行级安全策略,并且正确地配置了你的表。虽然把API Key直接放到前端去用有点反直觉,但这其实是supabase的一个强大特性,也就是RLS行级安全策略,它保证了我们即使在前端跟数据库交互,也能确保数据的安全。
等下一个章节,我们就来重点看这个行级的安全策略。这里我们先把SDK讲完,接下来就可以实现一些supabase的功能。这里我们先来一个用户注册,实现用户注册非常简单:
await supabase.auth.signUp({
email: 'tech-shrimp@outlook.com',
password: 'Supabase123!'
})
我们来测试一下,把项目启动起来,访问一下前端,然后我们来到Supabase的控制台,在authentication里面,就可以看到我们在页面上注册的那个账户,找到最右边,这里的状态是waiting for verification,就是还没有邮箱验证。来到注册用户的邮箱,收一下验证邮件,点一下这个确认链接,确认完毕,这个用户就完全生效了。
就这么几行就简单搞定了用户注册。用户登录只要把这个signUp改成signInWithPassword,就是使用邮箱加密码登录。在前面写个变量接收一下结果,最后把变量打印一下,我们再来试一下,
const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
email: 'tech-shrimp@outlook.com',
password: 'Supabase123!'
})
console.log(signInData)
刷新一下页面,在控制台就可以看到打印出来的用户信息,包括这里的session,用户的状态邮箱ID等等的各种信息。

这就是Supabase SDK的基础使用,几行代码就完成了用户的注册还有登录。
RLS行级安全策略
RLS行级安全策略它原本是postgres的一个原生功能,简单来说,就是约束了哪行数据可以被哪些用户修改或者读取。
在演示RLS之前,我们先在数据库里面建一个表。我们看到Supabase自带的这个用户表,它只有邮箱,还有电话等信息。我准备创建一个用户信息表,把用户的年龄等信息存一下,表明我叫user_info,注意一定要把这里的RLS启动起来。
添加我想要的字段,我们先来一个年龄字段,再来一个first name字段,再来一个last name字段。我需要把我的用户信息表跟这张系统表关联起来,所以我需要一个字段把这里的uid填进去。添加一个字段叫做user_id,它的类型选择uuid,跟系统表是一致的。这里随机生成我不需要。

然后在最下面我新建一个外键,需要把我们的user_id跟auth这个schema里面的用户表关联起来。这里左边我选择user_id,右边的关联项选择id,也就是我的user_info表的user_id字段跟系统表的auth.users的id字段,两个形成外键关联,保存一下。

然后我们回到左侧菜单,authentication里面,再新建一个用户,填个邮箱密码,创建,这样系统里面有两个用户了。再回到我们的业务表,我把这两个用户的基础信息都填一下,点击insert row,

第一个用户最下面的user_id我们选select record,选第一个用户,这样就把他的ID关联过来了。

保存,然后第二个用户年龄名字,在下面选择user_id,这里我选择这个用户,保存。我们在authentication的系统表里面有两个用户,在我们的业务表里面存储了这两个用户的年龄。
现在我的需求是,我只想让某个用户查看并且修改属于他自己的记录,而不能去查看或者修改别人的记录。
这里我们需要给业务表配置行级安全策略,点击这个按钮,
![]()
add RLS policy -->
![]()
create policy。我们选择这个select查询,右侧给了一些模板,我们选择最下面这一个

enable user to view their own data。这个模板的意思是登录用户只能读取属于他自己的那一条数据。上面这些都是固定的写法,我们主要看第7行,七行的意思是获取登录用户的ID,这个ID必须跟我user_info表的user_id匹配起来,也就是这个登录用户只能读取属于他自己的那一条数据,这也就是行级安全策略,把它保存一下。

登录用户只能看到属于他自己的数据。有了这个安全保障,我们可以直接把查询语句写到前端代码里面,supabase通过行级的安全策略保障了数据的安全性。我们来写一下查询语句,查询语句非常简单:supabase.from('user_info').select('*').eq('first_name', 'tech')。这里我要查询first_name等于tech的数据,我们来试一下。
const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
email: 'tech-shrimp@outlook.com',
password: 'Supabase123!',
})
const { data, error } = await supabase
.from('user_info')
.select('*')
.eq('first_name', 'Tech')
console.log('数据:', data)
console.log('错误:', error)
刷新一下页面,我们看到数据被查询出来了,用户的年龄,他的名字都被查询出来了。

我这里想查询别人的数据看看可不可以。这里我把first name换一下,换成数据库里面的另外一个用户test。

刷新一下页面,我们看到这里数据空的,

行级安全策略保证了当前的登录用户是不可能看到别人的数据的。
我们在浏览器控制台->network最下面可以看到这次查询的网络请求。Supabase SDK会自动的把这种select的语句转换成http 的get方法,包括表名,然后select的字段,后面的条件都写到了这个get方法里面。

我们看到这个请求里面最重要的部分,是在header里面的authentication里面,有一个bearer里面的JWT TOKEN,这个TOKEN也就是当前登录用户的令牌,只有这个令牌跟后面的行级安全策略匹配起来,才能查询到数据。

我这里面还有一些表没有配过行级安全策略,这些表就能随便查吗?比如这里我们看一下test表,点击这个
![]()
ADD RLS Policy。这里写了通过supabase API现在没有一行数据能被查询到,因为行级安全策略还没有配置,也就是没有配过RLS的表,通过SDK是完全查询不到的。

只有通过后台,或者这种直连数据库的形式,才能查询到这些表的数据。
RLS除了能保证数据的读取,还能保证数据的写入。我们再来新建一条策略,create policy。这里我们选中insert,模板的话选择这个,也就是用户只能插入跟自己有关的数据。

我们看到这里的条件跟刚才的select是一样的,这样点击save。我把业务表里面这两条测试数据删除掉,然后我们来修改代码,直接从前端网页来插入数据。插入数据的代码就这么写:supabase from后面是表明,表明后面就是insert,接下来就是需要插入的数据: first_name, last_name, 年龄, user_id。
我是从登录的账号里面取用户的ID,也就是说它只插入user_id等于自己的数据。
const { data: signInData, error: signInError } = await supabase.auth.signInWithPassword({
email: 'tech-shrimp@outlook.com',
password: 'Supabase123!',
})
const { data: data, error: error } = await supabase
.from('user_info')
.insert([
{
first_name: 'Tech',
last_name: 'Shrimp',
age: 28,
user_id: signInData?.user?.id
}
])
.select()
console.log('数据:', data)
console.log('错误:', error)
我们来试一下,刷新一下网页,成功打印了日志,我们来到后台,看到数据也被成功插入了数据库。
我们的行级安全策略约定了用户只能插入跟自己有关的数据,如果我改一下user_id,看看能不能去插别人的ID。刷新一下页面,看一下控制台,这里报了403 forbidden。

我们看到这里的报错:新插入的行违反了行级安全策略。我们的行级安全策略要求只能插入跟自己相关的数据,你不可能去修改别人的数据。从这个例子,我们看到行级安全策略的强大之处。这也就解释了为什么我们使用supabase可以把数据库的操作语句写到前端代码里面。
文件存储
接下来我们看另外一个重要功能storage,也就是文件存储。我们先来看一下它的基础使用。storage用来存放文件,这里我们点击add new bucket,

先创建一个存储桶,给存储桶起个名字,点击create。随便找个文件就可以拖拽进去,我们可以查看下载上传的文件,还有获取它的链接,可以把它当做一个图床使用。这个存储桶功能是适配了S3标准的存储协议的,我们可以通过这个地址使用S3协议来管理里面的文件。

同样的存储桶也可以配置它的安全措施,使用Supabase SDK直接在前端对存储桶进行操作。
这里我们来看一个例子,我们先来到policy,在存储桶这里新建一个policy,这里我选择第二个模板,也就是用户只能操作跟他的用户ID相同名字的文件夹。

右下角点击创建,我把这些权限都勾选上,点击保存。我准备把这个网页改造一下,变成一个上传的页面。我让AI帮我写了一个测试页面,还是用我这套账号名密码。核心上传代码在这里:supabase.storage.form是我这个存储桶的名字,接下来就是上传,指定一个路径,然后指定一个文件。

我们来试一下,看到用户已经登录了,这里我选择一个文件,我随便填一个路径,点击上传。我们看到这里报错了,他违反了行级安全策略。

我们的安全策略里面约束了,这个文件只能上传到跟他用户ID同名的文件夹里面。所以这里随便填一个文件夹是上传不上去的。我把用户的ID复制一下,我们把文件夹的名字改成用户的ID,再次点击上传。这次上传成功,我们去后台看一下。在存储桶里面可以看到用户的文件夹,在文件夹里面就可以看到他上传进来的文件。

我们使用的这个云服务版本,免费用户的最大存储空间有一定的限制:数据库最大使用500 MB,然后存储桶最大可以使用1GB。如果空间不够,我们当然也可以进行本地部署,视频的最后我会介绍如何进行本地部署。

边缘函数
Edge Function,
![]()
也就是边缘函数。Edge Function的功能非常像Cloudflare Worker,我之前有一期完整视频介绍什么是边缘函数,supabase的边缘函数跟我之前讲的几乎一模一样,这里我就不赘述了。
https://www.bilibili.com/video/BV1iv8CzVE2w/

实时推送
下一个功能是这里的RealTime,简单来说就是推送功能。我们可以配置一个触发器来监听数据库的变化,每当数据库有变化的时候,它就会发送一个Websocket的通知,然后通过Supabase的SDK把这个消息推送到网页端。比如,我们想把一个消息在客户端进行弹窗提醒,我我们就可以建一个提醒表,然后来订阅这个表的变化,每当发现表里面插入的数据跟自己有关,就会在客户端弹一个窗进行提醒。我们可以根据123 3个步骤,把一个实时推送配置好。这里由于本期视频篇幅所限,我就不详细演示了。
MCP
supabase下一个重要功能是MCP。我们来到文档站,搜索MCP,找到第二个。

可以根据这里的文档,把MCP安装到AI工具里面,让AI获得操作Supabase的能力。在上期视频里面,我对Supabase MCP有过完整介绍了。感兴趣的观众朋友们可以去看一下。
https://www.bilibili.com/video/BV1ZJsBznEt3

Supabase本地部署指引
接下来,我们看如何自己部署一个supabase。这里我们来到supabase的首页supabase.com,点击这个Docs

,也就是文档站。在build下面有一个self hosting

,也就是自托管,自部署。这里选择Docker的方式,下面有一串部署命令,我们来执行一下。
git clone --depth 1 https://github.com/supabase/supabase
mkdir supabase-project
cp -rf supabase/docker/* supabase-project
cp supabase/docker/.env.example supabase-project/.env
cd supabase-project
docker compose pull
docker compose up -d
supabase总共有13个组件,运行起来整个差不多需要4GB的内存。我没有这么大内存的Linux服务器,所以这里我就用我这台Windows电脑。
我新建一个文件夹,进来以后,右键在终端打开。我们第一件事需要在电脑上安装Docker,如果对Docker使用方式不熟悉,可以参考一下这期视频,里面有所有操作系统使用Docker的方式。https://www.bilibili.com/video/BV1THKyzBER6

把Docker Desktop启动起来,然后我们来执行官网上的命令。
首先第一个命令使用git 克隆命令把源代码克隆到本地。
git clone --depth 1 https://github.com/supabase/supabase
然后第二个命令新建一个文件夹。
mkdir supabase-project
第三个命令拷贝文件,不过Windows上不能这么直接执行。

我们来手动拷贝一下,来到这个supabase文件夹,找到docker,把这里面的所有东西复制一下,粘贴到supabase-project文件夹里面。
下一个命令是创建这个.env文件,这里我找到.env.example,把它复制一下创建一个.env文件

进来以后,需要改一些东西,这里有需要改的是它的前端端口,在Windows电脑上必须把这个端口改高一点,这里我在前面加个1,改成18,000。下面这个也改18443,这样配置文件也准备好了。

接下来我们执行这个命令CD进去
cd supabase-project
执行这个命令
docker compose pull
把所有需要的镜像都拉取下来,总共有13个组件,非常的多。
然后我们输入最后一个命令
docker compose up -d
把这13个容器一把全部启动起来。
启动完成以后,我们就可以来访问一下了。这里输入localhost:18000,注意端口填写我们配置文件里配的端口18000。
启动后需要填账号名密码,
账号名是supabase,密码填写这一串。this_password_is_insecure_and_should_be_updated
登录,这样,我们成功在本地部署好了。一个supabase应用。我们可以在数据库里面建表进行测试,然后刚才我们讲的数据库鉴权、文件存储、边缘函数这些功能,在自托管的版本里面也是有。
包括Supabase SDK也是可以正常用的,我们只需要把这里的地址,还有API Key换成我们本地部署的地址,还有API Key。在上面的connect里面选到APP framework,这里选到Vue.js,把这个地址替换到代码里面,包括API Key替换到代码里面,supabase SDK也可以完全正常使用

我们只需要找一个服务器,使用Docker把这一整套东西部署上去,就可以解锁supabase的全部能力。而且它的源代码在GitHub上面是完全开源的,使用的是宽松的apache 2.0协议,完全免费自由的商用。我想这也就是为什么他可以获得9万的星标。今天的视频就到这里,感谢大家点赞支持,我们下期再见。
1324

被折叠的 条评论
为什么被折叠?



