Supabase客户端初始化 #

一、基础客户端初始化 #

1.1 安装依赖 #

bash
# npm
npm install @supabase/supabase-js

# yarn
yarn add @supabase/supabase-js

# pnpm
pnpm add @supabase/supabase-js

1.2 基础初始化 #

typescript
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'https://your-project.supabase.co'
const supabaseKey = 'your-anon-key'

const supabase = createClient(supabaseUrl, supabaseKey)

1.3 完整配置选项 #

typescript
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.SUPABASE_URL!
const supabaseKey = process.env.SUPABASE_ANON_KEY!

const supabase = createClient(supabaseUrl, supabaseKey, {
  auth: {
    autoRefreshToken: true,
    persistSession: true,
    detectSessionInUrl: true,
    flowType: 'implicit',
    storage: window.localStorage,
    storageKey: 'supabase.auth.token',
    debug: false,
  },
  global: {
    headers: {
      'x-custom-header': 'custom-value',
    },
  },
  db: {
    schema: 'public',
  },
  realtime: {
    params: {
      eventsPerSecond: 10,
    },
  },
})

二、React项目集成 #

2.1 基础集成 #

typescript
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.REACT_APP_SUPABASE_URL!
const supabaseKey = process.env.REACT_APP_SUPABASE_ANON_KEY!

export const supabase = createClient(supabaseUrl, supabaseKey)

2.2 在组件中使用 #

tsx
// components/UserList.tsx
import { useState, useEffect } from 'react'
import { supabase } from '../lib/supabase'

interface User {
  id: number
  name: string
  email: string
}

export function UserList() {
  const [users, setUsers] = useState<User[]>([])
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetchUsers()
  }, [])

  async function fetchUsers() {
    const { data, error } = await supabase
      .from('users')
      .select('*')
    
    if (error) {
      console.error('Error fetching users:', error)
    } else {
      setUsers(data || [])
    }
    setLoading(false)
  }

  if (loading) return <div>Loading...</div>

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

2.3 使用Auth Helpers #

bash
# 安装Auth Helpers
npm install @supabase/auth-helpers-react @supabase/auth-helpers-nextjs
tsx
// App.tsx
import { SessionContextProvider } from '@supabase/auth-helpers-react'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.REACT_APP_SUPABASE_URL!,
  process.env.REACT_APP_SUPABASE_ANON_KEY!
)

function App() {
  return (
    <SessionContextProvider supabaseClient={supabase}>
      <YourApp />
    </SessionContextProvider>
  )
}

三、Next.js项目集成 #

3.1 安装依赖 #

bash
npm install @supabase/supabase-js @supabase/auth-helpers-nextjs

3.2 创建客户端 #

typescript
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}
typescript
// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // Server Component中调用setAll会失败
            // 这是预期的行为
          }
        },
      },
    }
  )
}

3.3 在Server Component中使用 #

tsx
// app/users/page.tsx
import { createClient } from '@/lib/supabase/server'

export default async function UsersPage() {
  const supabase = await createClient()
  
  const { data: users, error } = await supabase
    .from('users')
    .select('*')

  if (error) {
    return <div>Error loading users</div>
  }

  return (
    <ul>
      {users?.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

3.4 在Client Component中使用 #

tsx
// components/UserForm.tsx
'use client'

import { useState } from 'react'
import { createClient } from '@/lib/supabase/client'

export function UserForm() {
  const [name, setName] = useState('')
  const supabase = createClient()

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    
    const { error } = await supabase
      .from('users')
      .insert({ name })
    
    if (error) {
      console.error('Error:', error)
    } else {
      setName('')
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter name"
      />
      <button type="submit">Add User</button>
    </form>
  )
}

3.5 中间件配置 #

typescript
// middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  let supabaseResponse = NextResponse.next({
    request,
  })

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) =>
            request.cookies.set(name, value)
          )
          supabaseResponse = NextResponse.next({
            request,
          })
          cookiesToSet.forEach(({ name, value, options }) =>
            supabaseResponse.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  const {
    data: { session },
  } = await supabase.auth.getSession()

  if (!session && request.nextUrl.pathname.startsWith('/protected')) {
    const url = request.nextUrl.clone()
    url.pathname = '/login'
    return NextResponse.redirect(url)
  }

  return supabaseResponse
}

export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}

四、Vue项目集成 #

4.1 安装依赖 #

bash
npm install @supabase/supabase-js

4.2 创建插件 #

typescript
// plugins/supabase.ts
import { createClient } from '@supabase/supabase-js'
import type { App } from 'vue'

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY

export const supabase = createClient(supabaseUrl, supabaseKey)

export default {
  install(app: App) {
    app.provide('supabase', supabase)
  }
}

4.3 注册插件 #

typescript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import supabase from './plugins/supabase'

const app = createApp(App)
app.use(supabase)
app.mount('#app')

4.4 在组件中使用 #

vue
<!-- components/UserList.vue -->
<script setup lang="ts">
import { ref, onMounted, inject } from 'vue'
import type { SupabaseClient } from '@supabase/supabase-js'

const supabase = inject('supabase') as SupabaseClient

interface User {
  id: number
  name: string
  email: string
}

const users = ref<User[]>([])
const loading = ref(true)

onMounted(async () => {
  const { data, error } = await supabase
    .from('users')
    .select('*')
  
  if (error) {
    console.error('Error:', error)
  } else {
    users.value = data || []
  }
  loading.value = false
})
</script>

<template>
  <div v-if="loading">Loading...</div>
  <ul v-else>
    <li v-for="user in users" :key="user.id">
      {{ user.name }}
    </li>
  </ul>
</template>

4.5 使用Composable #

typescript
// composables/useSupabase.ts
import { inject } from 'vue'
import type { SupabaseClient } from '@supabase/supabase-js'

export function useSupabase() {
  const supabase = inject('supabase') as SupabaseClient
  return supabase
}
vue
<!-- 使用composable -->
<script setup lang="ts">
import { useSupabase } from '../composables/useSupabase'

const supabase = useSupabase()
</script>

五、React Native集成 #

5.1 安装依赖 #

bash
npm install @supabase/supabase-js
npm install react-native-url-polyfill
npm install @react-native-async-storage/async-storage

5.2 创建客户端 #

typescript
// lib/supabase.ts
import 'react-native-url-polyfill/auto'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'YOUR_SUPABASE_URL'
const supabaseKey = 'YOUR_SUPABASE_ANON_KEY'

export const supabase = createClient(supabaseUrl, supabaseKey, {
  auth: {
    storage: AsyncStorage,
    autoRefreshToken: true,
    persistSession: true,
    detectSessionInUrl: false,
  },
})

5.3 在组件中使用 #

tsx
// screens/HomeScreen.tsx
import { useState, useEffect } from 'react'
import { View, Text, FlatList } from 'react-native'
import { supabase } from '../lib/supabase'

export function HomeScreen() {
  const [users, setUsers] = useState([])

  useEffect(() => {
    fetchUsers()
  }, [])

  async function fetchUsers() {
    const { data, error } = await supabase
      .from('users')
      .select('*')
    
    if (!error && data) {
      setUsers(data)
    }
  }

  return (
    <View>
      <FlatList
        data={users}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <Text>{item.name}</Text>
        )}
      />
    </View>
  )
}

六、SvelteKit集成 #

6.1 安装依赖 #

bash
npm install @supabase/supabase-js @supabase/auth-helpers-sveltekit

6.2 创建客户端 #

typescript
// src/lib/supabaseClient.ts
import { createClient } from '@supabase/supabase-js'
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'

export const supabase = createClient(
  PUBLIC_SUPABASE_URL,
  PUBLIC_SUPABASE_ANON_KEY
)

6.3 服务端Hooks #

typescript
// src/hooks.server.ts
import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'
import { createServerClient } from '@supabase/ssr'
import type { Handle } from '@sveltejs/kit'

export const handle: Handle = async ({ event, resolve }) => {
  event.locals.supabase = createServerClient(
    PUBLIC_SUPABASE_URL,
    PUBLIC_SUPABASE_ANON_KEY,
    {
      cookies: {
        getAll() {
          return event.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            event.cookies.set(name, value, { ...options, path: '/' })
          )
        },
      },
    }
  )

  event.locals.safeGetSession = async () => {
    const {
      data: { session },
    } = await event.locals.supabase.auth.getSession()
    return session
  }

  return resolve(event, {
    filterSerializedResponseHeaders(name) {
      return name === 'content-range'
    },
  })
}

七、配置选项详解 #

7.1 Auth配置 #

typescript
auth: {
  autoRefreshToken: true,
  persistSession: true,
  detectSessionInUrl: true,
  flowType: 'implicit' | 'pkce',
  storage: customStorage,
  storageKey: 'supabase.auth.token',
  debug: false,
}

7.2 自定义存储 #

typescript
// 自定义存储适配器
const customStorage = {
  getItem: (key: string) => {
    return localStorage.getItem(key)
  },
  setItem: (key: string, value: string) => {
    localStorage.setItem(key, value)
  },
  removeItem: (key: string) => {
    localStorage.removeItem(key)
  },
}

const supabase = createClient(url, key, {
  auth: {
    storage: customStorage,
  },
})

7.3 全局配置 #

typescript
global: {
  headers: {
    'x-application-name': 'my-app',
  },
  fetch: customFetch,
}

八、类型定义 #

8.1 生成类型 #

bash
# 登录Supabase
supabase login

# 链接项目
supabase link --project-ref your-project-ref

# 生成类型
supabase gen types typescript --local > lib/database.types.ts

8.2 使用类型 #

typescript
// lib/database.types.ts
export type Json =
  | string
  | number
  | boolean
  | null
  | { [key: string]: Json | undefined }
  | Json[]

export interface Database {
  public: {
    Tables: {
      users: {
        Row: {
          id: number
          name: string
          email: string
          created_at: string
        }
        Insert: {
          id?: number
          name: string
          email: string
          created_at?: string
        }
        Update: {
          id?: number
          name?: string
          email?: string
          created_at?: string
        }
      }
    }
  }
}
typescript
// 使用类型
import { createClient } from '@supabase/supabase-js'
import type { Database } from './database.types'

const supabase = createClient<Database>(url, key)

// 现在有完整的类型支持
const { data } = await supabase
  .from('users')
  .select('*')
// data 类型为 { id: number; name: string; email: string; created_at: string }[]

九、错误处理 #

9.1 统一错误处理 #

typescript
// lib/supabase-error.ts
export function handleSupabaseError(error: any) {
  if (error) {
    console.error('Supabase Error:', error)
    
    switch (error.code) {
      case 'PGRST116':
        return '数据不存在'
      case '23505':
        return '数据已存在'
      case '42501':
        return '权限不足'
      default:
        return error.message || '操作失败'
    }
  }
  return null
}

9.2 使用示例 #

typescript
import { handleSupabaseError } from './lib/supabase-error'

async function fetchUser(id: number) {
  const { data, error } = await supabase
    .from('users')
    .select('*')
    .eq('id', id)
    .single()
  
  const errorMessage = handleSupabaseError(error)
  if (errorMessage) {
    throw new Error(errorMessage)
  }
  
  return data
}

十、总结 #

客户端初始化检查清单:

步骤 状态
安装依赖
创建客户端
配置环境变量
测试连接
生成类型定义
配置错误处理

下一步,让我们学习数据库基础操作!

最后更新:2026-03-28