Nuxt3 实战 (七):Supabase 数据库配置全攻略

作者:热心市民鹿先生2025.10.13 17:30浏览量:4

简介:本文详细讲解如何在 Nuxt3 项目中集成 Supabase 数据库,涵盖环境准备、API 密钥配置、安全连接、CRUD 操作及错误处理等关键步骤,助力开发者快速构建全栈应用。

Nuxt3 实战 (七):Supabase 数据库配置全攻略

在 Nuxt3 开发中,数据库的配置与集成是构建全栈应用的核心环节。Supabase 作为开源的 Firebase 替代方案,提供 PostgreSQL 数据库、实时订阅、身份验证等功能,其 Serverless 特性与 Nuxt3 的 SSR/SSG 模式高度契合。本文将系统讲解如何在 Nuxt3 项目中配置 Supabase 数据库,涵盖环境准备、API 密钥管理安全连接、CRUD 操作及错误处理等关键环节。

一、环境准备与 Supabase 项目创建

1.1 注册 Supabase 账号并创建项目

访问 Supabase 官网 完成注册,进入控制台后点击 “New Project” 创建项目。需填写项目名称、选择数据库区域(建议选择离用户最近的区域以降低延迟),并设置密码。项目创建后,Supabase 会自动生成 PostgreSQL 数据库及配套的 REST/GraphQL API。

1.2 获取 API 密钥与连接配置

在项目仪表盘的 “Settings” > “API” 选项卡中,可找到以下关键信息:

  • SUPABASE_URL:项目的基础 URL(如 https://xyz.supabase.co
  • SUPABASE_ANON_KEY:匿名公开密钥,用于前端无身份验证的查询
  • SUPABASE_SERVICE_ROLE_KEY:服务角色密钥,用于后端高权限操作(需谨慎保管)

⚠️ 安全提示:切勿将 SUPABASE_SERVICE_ROLE_KEY 暴露在前端代码中,建议通过环境变量或后端 API 传递。

二、Nuxt3 项目集成 Supabase

2.1 安装 Supabase 客户端库

在 Nuxt3 项目中安装官方客户端库:

  1. npm install @supabase/supabase-js
  2. # 或
  3. yarn add @supabase/supabase-js

2.2 创建 Supabase 客户端工具模块

server/apiutils 目录下创建 supabase.ts 文件,封装客户端初始化逻辑:

  1. import { createClient } from '@supabase/supabase-js'
  2. const supabaseUrl = process.env.SUPABASE_URL || ''
  3. const supabaseAnonKey = process.env.SUPABASE_ANON_KEY || ''
  4. export const supabase = createClient(supabaseUrl, supabaseAnonKey)
  5. // 服务端专用客户端(需传递 serviceRoleKey)
  6. export const createServiceSupabase = (serviceRoleKey: string) => {
  7. return createClient(supabaseUrl, serviceRoleKey)
  8. }

2.3 配置环境变量

.env 文件中添加:

  1. SUPABASE_URL=your_project_url
  2. SUPABASE_ANON_KEY=your_anon_key
  3. # 服务端密钥通过运行时注入(如通过 Nuxt3 的 runtimeConfig)

nuxt.config.ts 中配置:

  1. export default defineNuxtConfig({
  2. runtimeConfig: {
  3. supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY || '',
  4. public: {
  5. supabaseUrl: process.env.SUPABASE_URL || '',
  6. supabaseAnonKey: process.env.SUPABASE_ANON_KEY || ''
  7. }
  8. }
  9. })

三、数据库操作实战

3.1 查询数据(GET 请求)

在组件或 API 路由中查询数据:

  1. // 组件中直接使用(需处理异步)
  2. <script setup lang="ts">
  3. const { data: posts } = await useAsyncData('posts', async () => {
  4. const { data, error } = await supabase.from('posts').select('*')
  5. if (error) throw error
  6. return data
  7. })
  8. </script>
  9. // 或通过 API 路由(推荐)
  10. // server/api/posts.get.ts
  11. export default defineEventHandler(async (event) => {
  12. const { data, error } = await supabase.from('posts').select('*')
  13. if (error) throw createError({ statusCode: 500, message: error.message })
  14. return data
  15. })

3.2 插入数据(POST 请求)

  1. // 组件中提交表单
  2. const submitForm = async () => {
  3. const { error } = await supabase.from('posts').insert({
  4. title: 'Nuxt3 实战',
  5. content: '配置 Supabase 数据库...'
  6. })
  7. if (error) alert('提交失败')
  8. }
  9. // API 路由示例
  10. // server/api/posts.post.ts
  11. export default defineEventHandler(async (event) => {
  12. const body = await readBody(event)
  13. const { error } = await supabase.from('posts').insert(body)
  14. if (error) throw createError({ statusCode: 500, message: error.message })
  15. return { success: true }
  16. })

3.3 实时数据订阅

Supabase 支持 PostgreSQL 的 LISTEN/NOTIFY 机制,可通过以下方式实现实时更新:

  1. // 组件中订阅
  2. onMounted(async () => {
  3. const { data } = supabase.from('posts').on('*', (payload) => {
  4. console.log('数据变更:', payload)
  5. // 更新本地状态
  6. }).subscribe()
  7. onUnmounted(() => {
  8. supabase.removeSubscription(data.subscription)
  9. })
  10. })

四、安全与性能优化

4.1 行级安全(RLS)策略

在 Supabase 控制台的 “Database” > “RLS Policies” 中,可为表配置细粒度权限。例如,仅允许用户访问自己的数据:

  1. CREATE POLICY "Users can view their own profile" ON profiles
  2. FOR SELECT USING (auth.uid() = id);

4.2 服务端渲染(SSR)优化

对于需要身份验证的路由,使用 Nuxt3 的 useFetchuseAsyncData 时,需在服务端传递密钥:

  1. // server/api/protected.get.ts
  2. export default defineEventHandler(async (event) => {
  3. const config = useRuntimeConfig()
  4. const serviceSupabase = createServiceSupabase(config.supabaseServiceRoleKey)
  5. const { data, error } = await serviceSupabase.from('protected_data').select('*')
  6. if (error) throw createError({ statusCode: 403, message: '无权限' })
  7. return data
  8. })

4.3 错误处理与日志

统一封装错误处理逻辑:

  1. // utils/errorHandler.ts
  2. export const handleSupabaseError = (error: any) => {
  3. switch (error.code) {
  4. case 'PGRST116': return '资源不存在'
  5. case '42501': return '权限不足'
  6. default: return '服务器错误,请稍后重试'
  7. }
  8. }

五、进阶配置

rage-">5.1 存储桶(Storage)集成

Supabase 存储支持文件上传与 CDN 加速:

  1. // 上传文件
  2. const { error } = await supabase.storage
  3. .from('avatars')
  4. .upload(`user_${auth.user().id}`, file)
  5. // 生成访问 URL
  6. const { data } = supabase.storage
  7. .from('avatars')
  8. .getPublicUrl(`user_${auth.user().id}`)

5.2 自定义函数与触发器

在 Supabase 控制台的 “Database” > “Extensions” 中安装 pg_net 等扩展,或通过 SQL 创建触发器:

  1. CREATE OR REPLACE FUNCTION notify_new_post()
  2. RETURNS TRIGGER AS $$
  3. BEGIN
  4. PERFORM pg_notify('new_post', row_to_json(NEW)::text);
  5. RETURN NEW;
  6. END;
  7. $$ LANGUAGE plpgsql;
  8. CREATE TRIGGER post_trigger
  9. AFTER INSERT ON posts
  10. FOR EACH ROW EXECUTE FUNCTION notify_new_post();

六、总结与最佳实践

  1. 密钥管理:始终通过环境变量传递敏感信息,避免硬编码。
  2. RLS 策略:默认启用行级安全,遵循最小权限原则。
  3. 实时功能:合理使用订阅机制,避免过度订阅导致性能问题。
  4. 错误处理:统一封装错误码,提供用户友好的提示。
  5. 服务端渲染:高权限操作通过 API 路由实现,避免泄露密钥。

通过以上配置,Nuxt3 项目可高效集成 Supabase 数据库,实现从数据存储到实时更新的全栈能力。实际开发中,建议结合 Supabase 的身份验证系统(如 GitHub OAuth)进一步完善用户管理流程。