Giới thiệu
Supabase và Next.js đang trở thành cặp đôi đáng chú ý trong hệ sinh thái JavaScript hiện đại. Trong khi Next.js cung cấp khung framework React linh hoạt và hiệu năng cao, Supabase mang đến giải pháp backend-as-a-service hoàn chỉnh với cơ sở dữ liệu PostgreSQL, xác thực, lưu trữ tệp và nhiều tính năng khác. Việc kết hợp chúng giúp các nhà phát triển xây dựng ứng dụng web hoàn chỉnh nhanh chóng mà không cần phải quản lý server phức tạp.
Thiết lập dự án
Để bắt đầu, cần khởi tạo một dự án Next.js mới và kết nối với Supabase. Supabase cung cấp gói @supabase/supabase-js giúp tương tác với API một cách đơn giản. Trước tiên, tạo file .env.local trong thư mục gốc của dự án và thêm các biến môi trường:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
Sau đó, tạo một file lib/supabase.js để khởi tạo client:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
Xác thực người dùng
Supabase hỗ trợ nhiều nhà cung cấp xác thực như Google, GitHub, Apple, cũng như email/password truyền thống. Để thêm form đăng nhập, có thể tạo một component đơn giản:
import { useState } from 'react'
import { supabase } from '@/lib/supabase'
export default function SignIn() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const handleSignIn = async (e) => {
e.preventDefault()
const { error } = await supabase.auth.signInWithPassword({
email,
password
})
if (error) console.log(error)
}
return (
<form onSubmit={handleSignIn}>
<input type="email" value={email} onChange={e => setEmail(e.target.value)} />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} />
<button type="submit">Đăng nhập</button>
</form>
)
}
Quản lý dữ liệu với Row Level Security
Một trong những tính năng mạnh mẽ của Supabase là Row Level Security (RLS), cho phép kiểm soát truy cập dữ liệu ở cấp độ hàng. Trước khi ứng dụng có thể đọc hoặc ghi dữ liệu, cần bật RLS trên bảng và định nghĩa các policy. Ví dụ, để user chỉ có thể xem và chỉnh sửa dữ liệu của chính mình:
-- Bật RLS
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;
-- Tạo policy
CREATE POLICY "Users can view own documents." ON documents
FOR SELECT USING (auth.uid() = user_id);
CREATE POLICY "Users can insert own documents." ON documents
FOR INSERT WITH CHECK (auth.uid() = user_id);
Quảng cáo
300x250 In-Content Advertisement
CREATE POLICY "Users can update own documents." ON documents
FOR UPDATE USING (auth.uid() = user_id);
Tương tác với cơ sở dữ liệu
Sau khi đã thiết lập xong RLS, có thể thực hiện các thao tác CRUD một cách an toàn. Ví dụ, để lấy danh sách tài liệu của user hiện tại:
import { useState, useEffect } from 'react'
import { supabase } from '@/lib/supabase'
export default function Documents() {
const [documents, setDocuments] = useState([])
useEffect(() => {
const fetchDocuments = async () => {
const { data, error } = await supabase
.from('documents')
.select('*')
if (error) console.log(error)
else setDocuments(data)
}
fetchDocuments()
}, [])
return (
<div>
{documents.map(doc => (
<div key={doc.id}>{doc.title}</div>
))}
</div>
)
}
Nâng cao: Real-time và Storage
Supabase cung cấp subscription real-time giúp ứng dụng phản hồi tức thì khi dữ liệu thay đổi. Để lắng nghe thay đổi trên bảng documents:
useEffect(() => {
const mySubscription = supabase
.from('documents')
.on('INSERT', payload => {
console.log('New document:', payload.new)
})
.subscribe()
return () => supabase.removeSubscription(mySubscription)
}, [])
Ngoài ra, Supabase Storage cho phép upload và quản lý file một cách dễ dàng. Để upload ảnh:
const handleUpload = async (e) => {
const file = e.target.files[0]
const filePath = ${user.id}/${file.name}
const { data, error } = await supabase.storage
.from('avatars')
.upload(filePath, file)
}
Kết luận
Việc tích hợp Supabase với Next.js giúp rút ngắn đáng kể thời gian phát triển backend. Từ xác thực, quản lý dữ liệu, real-time đến lưu trữ file đều được giải quyết trong một hệ sinh thái thống nhất. Tuy nhiên, cần lưu ý bật RLS để bảo mật dữ liệu và cân nhắc chi phí khi dự án mở rộng. Với những ứng dụng vừa và nhỏ, đây là lựa chọn tối ưu để tập trung vào trải nghiệm người dùng thay vì lo lắng về cơ sở hạ tầng.