954 字
5 分钟
使用 Next.js 和 Supabase 进行全栈开发:构建现代博客系统
什么是 Supabase?
Supabase 被誉为“开源版的 Firebase”。它不仅仅是一个数据库,而是一个高度集成的后端服务套件。其核心架构基于坚如磐石的 PostgreSQL,并在此基础上提供了开发者最急需的几种能力:
- PostgreSQL 数据库:完整的 SQL 支持,非 NoSQL。
- 用户认证 (Auth):内置 OAuth、魔术链接及传统的账号密码登录。
- 实时功能 (Realtime):监听数据库变更并同步至前端。
- 文件存储 (Storage):轻松托管图片、视频等媒体文件。
- 边缘函数 (Edge Functions):全球分布的无服务器代码执行环境。
核心优势:为什么不再选择 Firebase?
- 无供应商锁定:基于开源技术,你可以随时将其迁移到自己的服务器。
- 关系型力量:利用复杂的 SQL 查询、外键关系和事务,这在 NoSQL(如 Firestore)中很难处理。
- RLS(行级安全):直接在数据库层面处理权限控制,前端 API 调用更加安全、简洁。
步骤一:环境搭建与依赖安装
1. 创建 Next.js 应用
npx create-next-app@latest next-supabase-blog --tailwindcd next-supabase-blog2. 安装 Supabase 客户端及工具
注意:我们现在通常使用更精简的 @supabase/auth-helpers-nextjs 来处理 Next.js 的服务端渲染(SSR)认证。
npm install @supabase/supabase-js react-simplemde-editor react-markdown uuid步骤二:数据库建模与安全策略 (RLS)
在 Supabase 控制台的 SQL Editor 中运行以下脚本。这里定义了博客表结构,并启用了 Row Level Security,这是 Supabase 安全的核心。
-- 创建帖子表CREATE TABLE posts ( id uuid DEFAULT uuid_generate_v4() primary key, user_id uuid references auth.users not null, title text not null, content text not null, inserted_at timestamp with time zone default now() not null);
-- 开启行级安全ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
-- 策略 1:允许所有人查看帖子(公共访问)CREATE POLICY "Public access to posts" ON posts FOR SELECT USING (true);
-- 策略 2:仅允许认证用户创建帖子CREATE POLICY "Authenticated users can insert" ON posts FOR INSERT WITH CHECK (auth.uid() = user_id);
-- 策略 3:仅允许作者本人修改/删除CREATE POLICY "Authors can update their own posts" ON posts FOR UPDATE USING (auth.uid() = user_id);步骤三:初始化 Supabase 客户端
在项目根目录创建 .env.local,填入你的凭证:
NEXT_PUBLIC_SUPABASE_URL=你的项目地址NEXT_PUBLIC_SUPABASE_ANON_KEY=你的匿名Key创建 lib/supabaseClient.js:
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY);步骤四:实现用户状态监听
在 pages/_app.js(或根布局组件)中,我们需要监听用户的登录状态,以便实时更新 UI。
import { useState, useEffect } from 'react';import { supabase } from '../lib/supabaseClient';
function MyApp({ Component, pageProps }) { const [session, setSession] = useState(null);
useEffect(() => { // 获取当前会话 supabase.auth.getSession().then(({ data: { session } }) => { setSession(session); });
// 监听状态变更(登录/退出) const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => { setSession(session); });
return () => subscription.unsubscribe(); }, []);
return <Component {...pageProps} session={session} />;}步骤五:创建帖子(客户端 CRUD)
在 pages/create-post.js 中,我们使用 Supabase 的 from().insert() 方法。
async function createNewPost() { if (!title || !content) return;
// 在新版 SDK 中,应先获取当前用户 const { data: { user } } = await supabase.auth.getUser();
const { error } = await supabase .from('posts') .insert([{ title, content, user_id: user.id }]);
if (error) { console.error('创建失败:', error.message); } else { router.push('/'); }}最佳实践与避坑指南
- 异步获取用户:永远不要依赖本地缓存的用户对象。在执行写入操作前,始终调用
await supabase.auth.getUser()以确保会话有效且未被篡改。 - 环境变量命名:在 Next.js 中,任何需要在客户端访问的环境变量必须以
NEXT_PUBLIC_开头。 - RLS 必开:如果你忘记开启 RLS,任何知道你 API Key 的人都可以通过控制台删除你的整个数据库。
总结
结合 Next.js 的高效渲染和 Supabase 的全能后端,开发者可以在不到一小时内搭建起一个具备生产级安全性的应用。
使用 Next.js 和 Supabase 进行全栈开发:构建现代博客系统
https://sw.rscclub.website/posts/nextsup/