news 2026/9/7 9:28:57

基于 Supabase Realtime Presence 与 Auth 构建 Next.js 在线用户状态应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Supabase Realtime Presence 与 Auth 构建 Next.js 在线用户状态应用

基于 Supabase Realtime Presence 与 Auth 构建 Next.js 在线用户状态应用

【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase

本文基于开源仓库supabase中 examples/realtime/nextjs-auth-presence 官方示例,系统讲解如何将 Supabase Auth 与 Realtime Presence 结合,在 Next.js 应用中实时展示"当前谁正在查看页面"。读完本文你将掌握 channel 的创建与订阅、presence 的 track/join/sync 事件流,以及服务端渲染下基于 cookie 的会话鉴权实现,可直接复用到聊天室、在线协作文档、协作白板等多人实时场景。

示例项目定位与技术栈

该示例演示的是 Realtime Presence 的核心价值:同一时刻、同一个 channel 上,每个连接的客户端向其他客户端广播"我在这里"的状态。用户通过 Supabase Auth 登录后,页面即可看到所有"在线且正在浏览该页面"的用户列表。

项目技术构成(见 package.json):

  • 前端框架:Next.js(^13.1.6)+ React 18;
  • Supabase 客户端@supabase/ssr(latest)与@supabase/supabase-js(^2),其中 supabase-js v2 内置了对 Realtime Presence 的完整支持;
  • 后端:Supabase 托管的 Postgres 数据库(含 Realtime 能力),通过 supabase.com/dashboard 创建与管理。

从源码结构看(pages/下有index.tsxlogin.tsxprofile.tsx_app.tsx),整个应用围绕三个页面展开:/(在线用户主页)、/login(登录/注册)、以及基于 SSR 鉴权的 Profile 页面,路由采用 Next.js Pages Router 约定。

理解 Realtime Presence 的三个核心事件

Presence 是 Realtime 提供的"用户在线状态"通道能力。示例中 pages/index.tsx 展示了三类 API 的组合用法,它们是理解整段逻辑的钥匙:

  1. channel.on('presence', { event: 'sync' }, callback):当频道内 presence 状态整体同步(任何客户端加入或离开导致状态集变化)时触发,回调中通过channel.presenceState()获取当前完整在线状态集合,用于刷新 UI 列表;
  2. channel.on('presence', { event: 'join' }, callback):有新客户端加入并track自己的状态时触发,回调参数中的newPresences携带新加入者的状态载荷;
  3. channel.subscribe(callback):执行真实订阅。回调参数status'SUBSCRIBED'时表示连接成功,此时才能调用channel.track(...)把自己的状态写入频道。

在示例中还有一个config.presence.key的设置(订阅时传入),用于把当前用户的 email 作为该用户在频道内的状态 key——这决定了presenceState()返回对象中键的组织方式,是后续渲染"用户列表"的依据。

从零开始的完整搭建步骤

第一步:创建 Supabase 项目并启用用户管理

  1. 注册并登录 supabase.com/dashboard,创建一个新项目,等待数据库启动完成;
  2. 运行"User Management Starter"Quickstart。该操作会为用户管理创建 user 相关的数据表与 profile 表——Auth 登录后返回的User对象(含 email)即来自这一套用户体系,本示例全程依赖 email 作为展示身份;
  3. 在 Project Settings(齿轮图标)→ API 页签中,记录API URLpublishable key(anon key),后续配置环境变量需要用到。

说明:示例中的publishablekey 即客户端 API key,它在用户登录前提供"匿名访问"能力;用户登录后,请求会自动切换到用户自己的登录令牌(session),实现以当前用户身份访问数据库。

第二步:拉取示例并配置环境变量

将本仓库(或直接使用其中的nextjs-auth-presence目录)拉到本地后,在项目根目录创建.env.local文件。仓库已提供模板 sample.env.local,内容结构如下:

NEXT_PUBLIC_SUPABASE_URL="replace-this-with-your-supabase-instance" NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY="replace-this-with-your-supabasedb-anon-key"

将两个占位符分别替换为第一步取得的 API URL 与 publishable key。由于两个变量都以NEXT_PUBLIC_开头,它们会在构建期被内联进浏览器端 bundle,供客户端代码使用——这正是 Presence 这类纯客户端实时功能所必需的前提。

第三步:安装依赖并启动开发服务器

npm install npm run dev

用浏览器打开 http://localhost:3000 即可看到效果。项目自身提供的dev/build/start/lint/format脚本定义在 package.json 中,除npm run dev外,也支持npm run build && npm start以生产模式运行。

源码拆解:Auth 上下文与 Presence 主逻辑

全局 Supabase 客户端与用户状态(lib/supabase-context.tsx)

lib/supabase-context.tsx 是整个应用的"地基",它做了三件事:

  1. 模块级调用createBrowserClient创建单例浏览器端客户端,读取两个NEXT_PUBLIC_环境变量作为参数;
  2. 通过 React Context 向全树暴露supabase客户端与user状态;
  3. useEffect中调用supabase.auth.getUser()初始化用户,并订阅onAuthStateChange,使得登录态变化时(session?.user)能同步刷新user

对外暴露的useSupabaseClient()useUser()两个 Hook,被登录页和主页直接消费——组件从 Context 拿客户端与当前用户,不需要各自创建实例。

同时,_app.tsx 中的MyAppInner也在监听onAuthStateChange,并在SIGNED_IN时跳转/SIGNED_OUT时跳转/login,实现全局性的登录态驱动路由。注意SIGNED_IN事件同时被supabase-context.tsx_app.tsx两处使用:前者负责更新 React 状态,后者负责页面导航,职责互补。

在线用户列表(pages/index.tsx 的 Presence 逻辑)

pages/index.tsx 的组件侧核心代码如下:

const channel = supabaseClient.channel('online-users', { config: { presence: { key: this_user?.email ? this_user?.email : 'Unknown', }, }, }) channel.on('presence', { event: 'sync' }, () => { const presentState = channel.presenceState() setUserState({ ...presentState }) }) channel.on('presence', { event: 'join' }, ({ newPresences }) => { console.log('New users have joined: ', newPresences) }) channel.subscribe(async (status) => { if (status === 'SUBSCRIBED') { const status = await channel.track({ user_name: this_user?.email ? this_user?.email : 'Unknown', }) console.log('status: ', status) } })

关键流程:

  • 创建名为online-users的频道,并把用户 email(未登录时为'Unknown')设为 presence key;
  • sync事件到来后用channel.presenceState()全量快照刷新 React state;
  • 订阅成功后track当前用户(载荷为{ user_name: email }),告诉频道"我在线";
  • 视图层遍历userState的 key(即各在线用户的 email key),渲染出"Hi xxx"列表,同时提供 Sign out 按钮(见 pages/index.tsx)。

需要指出:示例中useEffect的依赖数组为空[],意味着频道创建与订阅只在页面挂载时执行一次;useState中 userState 以{}初始化并随后被sync快照覆盖。若在真实项目里复用此模式,建议关注组件卸载时的退订清理,并考虑把用户 email 变更纳入依赖,避免多用户切换时状态错乱。

服务端鉴权:getServerSideProps 中的 createServerClient

pages/index.tsx 同文件里还演示了 Pages Router 下的 SSR 会话校验:

  • 使用createServerClient(url, key, { cookies })创建服务端客户端,其中cookies.getAll()读取请求 Cookie,cookies.setAll()把需要写入的 session cookie 序列化后写回响应头(依赖cookie包的serialize);
  • 随后supabase.auth.getUser()校验会话,若没有 user 则redirect/login
  • 校验通过则将user作为 props 传给页面组件。

同样的 cookie 注入模式也完整复刻在 pages/profile.tsx 中,说明这是该示例在服务端保护路由时的统一写法——它是@supabase/ssr在 Next.js Pages Router 中的标准集成姿势。

登录/注册页(pages/login.tsx)

pages/login.tsx 实现了一个可在 sign-in / sign-up 间切换的表单:

  • signInWithPassword({ email, password })处理登录;
  • signUp({ email, password, options: { emailRedirectTo } })处理注册,注册后若无 session(即需要邮件确认时),页面提示用户查收确认链接;
  • 已登录用户会直接渲染出完整 user 对象的 JSON 视图并提供登出按钮(pages/login.tsx)。

注意密码框的minLength={6}与浏览器端autoComplete属性,都是为配合 Supabase Auth 对密码的基础约束而设。

如何验证 Presence 效果

按 README 提供的测试路径逐项操作:

  1. 访问http://localhost:3000,会被自动重定向到登录/注册页;
  2. 未注册则先 Sign up,再使用邮箱 + 密码 Sign in;
  3. 登录后跳回主页,页面会列出你的 email(形如Hi your@email.com);
  4. 另开一个浏览器窗口,用另一个账号登录;
  5. 切回第一个窗口,观察在线用户列表已自动更新,新登录的账号出现在列表中。

验证要点:列表的实时更新依赖sync事件触发setUserState的 React 重渲染,因此无需手动刷新页面即可看到第二个用户出现;当第二个窗口登出或关闭时,第一个窗口的列表同样会自动移除该用户。打开浏览器 DevTools Console,可以看到New users have joined:status:的日志输出,它们分别来自join事件回调和track的返回结果。

部署建议

由于这是一个 Next.js 应用,最简单的部署方式是推到 Vercel 平台(在 Vercel 项目面板中重新填入两个NEXT_PUBLIC_环境变量后执行部署)。仓库内也保留了 Vercel 相关的默认静态资源(public/vercel.svg),说明其默认部署目标即 Vercel;若部署到自有服务器,则使用npm run build && npm start即可。无论何种方式,请确保生产环境变量中的 URL 指向可被公网访问的 Supabase 项目实例。

后续演进方向

README 的 "Conclusion/Next Steps" 部分给出了从示例走向完整产品的建议,与仓库中已有的页面骨架可以一一对应:

  • 实现 Profile 页面pages/profile.tsx已具备 SSR 鉴权与用户信息展示,可扩展为可编辑资料的完整资料页;
  • 支持用户头像上传:可结合 Supabase Storage 上传头像并回写 profile 表;
  • 读取社交账号头像:启用 Auth 的 OAuth 登录(如 GitHub、Google)后,可从第三方返回的user_metadata中直接取到头像 URL。

此外,从工程角度,可将本示例与仓库同目录下的姊妹示例对照研读——examples/realtime/nextjs-authorization-demo 侧重 Realtime 频道级授权(Authorization),而本示例侧重 Presence 状态同步,两者结合可覆盖"谁能监听"与"谁在场"两个维度;仓库中的 Realtime 其余示例(如 Flutter 版多人游戏)也展示了 Presence 在更大并发场景下的应用形态。

小结

通过这一个约 300 行核心代码的示例,可以完整走通 Supabase 的"Auth 认证 → SSR 会话保护 → Realtime channel 订阅 → Presence track/join/sync 状态同步"整条链路。本文覆盖了官方 README 的全部操作步骤,并补充了 lib/supabase-context.tsx、pages/index.tsx、_app.tsx 与 pages/login.tsx 的源码级剖析。理解这四点,你就能在此基础上快速搭建属于自己的多人协作与在线状态产品。

【免费下载链接】supabaseThe Postgres development platform. Supabase gives you a dedicated Postgres database to build your web, mobile, and AI applications.项目地址: https://gitcode.com/GitHub_Trending/supa/supabase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 9:28:45

CMSSW入门指南:架构解析、环境搭建与最小分析实战

简介:CMSSW(Compact Muon Solenoid Software)是欧洲核子研究组织(CERN)大型强子对撞机CMS实验的核心离线数据分析框架,面向粒子物理科研人员、高能物理数据分析开发者及开源科学计算爱好者。该框架以 cmsR…

作者头像 李华
网站建设 2026/9/7 9:27:27

Cap 开源录屏快速上手:从安装到分享链接只要5分钟

Cap 开源录屏快速上手:从安装到分享链接只要5分钟 【免费下载链接】Cap Open source Loom alternative. Beautiful, shareable screen recordings. 项目地址: https://gitcode.com/GitHub_Trending/cap1/Cap Cap 是一款开源的 Loom 替代录屏工具:…

作者头像 李华
网站建设 2026/9/7 9:27:05

Android AIDL实战:从零实现跨进程通信Demo与避坑指南

简介:面向安卓初学者的AIDL入门示例项目,演示了通过AIDL接口实现跨进程通信(IPC)的完整流程。资源适合刚开始接触安卓组件间通信、希望掌握远程服务与客户端绑定机制的开发者,可直接导入Eclipse工程运行并观察调用效果…

作者头像 李华
网站建设 2026/9/7 9:26:15

java-web-苍穹外卖-day2-上:测试阶段区分+开发工具区分

nginx可以将前端发送的动态请求由nginx服务器转发到后端服务器(反向代理)提高前端访问速度---缓存后端响应数据负载均衡----将前端请求按照设定的规则分配给集群中的每台服务器策略轮询--默认weightleast_connfairip_hashurl_hash保证后端服务安全--将后端放在内网中, 将nginx作…

作者头像 李华
网站建设 2026/9/7 9:25:41

ESP32-S3驱动SPI触摸屏并接入LVGL完整指南

简介:面向ESP32-S3物联网开发者的LVGL电容触摸屏驱动资源包,基于ST7789显示控制器与CST816触摸芯片,给出完整的适配与示例代码,可帮助中高级嵌入式开发者快速搭建1.69寸屏的图形交互界面。压缩包共971个文件,大小17.39…

作者头像 李华
网站建设 2026/9/7 9:24:44

C#上位机三维可视化实战:Activiz/VTK点云与模型渲染笔记

简介:Activiz 实用案例下载包是一套面向VTK技术栈的交互式医学影像处理示例合集,特别适合使用C#或VB.NET进行科学可视化、医疗影像应用开发的工程师与研究者。案例基于Activiz(VTK的.NET封装),覆盖DICOM/NIFTI格式读取…

作者头像 李华