使用Supabase+Next.js页面路由时认证及database.types文件错误求助
Next.js页面路由 + Supabase认证配置及database.types文件解决方法
一、解决database.types文件缺失问题
lib/database.types.ts是Supabase生成的数据库类型定义文件,用于TypeScript类型校验,并非安装依赖时自动生成的,需要通过Supabase CLI手动生成:
- 安装Supabase CLI:
npm install -g supabase - 登录Supabase账号(会跳转浏览器完成授权):
supabase login - 绑定你的Supabase项目(项目ID可在Supabase控制台「项目设置」中找到):
supabase link --project-ref <你的项目ID> - 生成类型文件到指定目录:
supabase gen types typescript --linked > lib/database.types.ts
二、Next.js页面路由的Supabase认证配置步骤
1. 配置环境变量
在项目根目录创建.env.local文件,填入Supabase项目的核心参数:
NEXT_PUBLIC_SUPABASE_URL=你的Supabase项目URL NEXT_PUBLIC_SUPABASE_ANON_KEY=你的Supabase匿名密钥
2. 初始化Supabase客户端
创建lib/supabase.ts文件,引入类型并初始化客户端:
import { createClient } from '@supabase/auth-helpers-nextjs'; import type { Database } from './database.types'; export const supabase = createClient<Database>( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! );
3. 配置Middleware保护路由
修改middleware.ts,用类型化的客户端实现路由拦截:
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'; import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import type { Database } from './lib/database.types'; export async function middleware(req: NextRequest) { const res = NextResponse.next(); const supabase = createMiddlewareClient<Database>({ req, res }); // 校验用户认证状态 const { data: { user } } = await supabase.auth.getUser(); // 未认证用户重定向到登录页 if (!user) { return NextResponse.redirect(new URL('/login', req.url)); } return res; } // 指定需要保护的路由规则 export const config = { matcher: ['/dashboard/:path*', '/profile'], };
4. 登录页面示例(pages/login.tsx)
实现基础的账号密码登录逻辑:
import { useState } from 'react'; import { supabase } from '../lib/supabase'; import { useRouter } from 'next/router'; export default function LoginPage() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const router = useRouter(); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); const { error } = await supabase.auth.signInWithPassword({ email, password }); if (error) alert(error.message); else router.push('/dashboard'); }; return ( <form onSubmit={handleLogin} style={{ maxWidth: '300px', margin: '2rem auto' }}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="邮箱" required style={{ display: 'block', width: '100%', margin: '0.5rem 0', padding: '0.8rem' }} /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="密码" required style={{ display: 'block', width: '100%', margin: '0.5rem 0', padding: '0.8rem' }} /> <button type="submit" style={{ width: '100%', padding: '0.8rem', backgroundColor: '#2563eb', color: 'white', border: 'none', borderRadius: '4px' }}> 登录 </button> </form> ); }
内容的提问来源于stack exchange,提问作者harsh jani
相关产品推荐
相关产品推荐

