آموزش Supabase – بک اند برای React.js

سلام خدمت دوستان گرامی و همراهان آکادمی راهکارینو.
بعد از یک وقفه نسبتا طولانی، با یک مقاله آموزشی دیگه در زمینه ریکت و تکنولوژی های وابسته به آن در کنارتان هستیم. در این پست می خواهم سرویسی را خدمت شما معرفی کنم که می تواند جایگزین مناسبی برای فایربیس (FireBase) باشد.
معرفی Supabase:
اگر شما توسعه دهنده فرانت اند (front end developer) هستید و توانایی فنی یا زمان لازم برای توسعه بک اند پروژه خود را ندارید براحتی می توان از Supabase استفاده کنید. همانطور که در سایت Supabase بیان شده، این سرویس می تواند امکانات زیادی در اختیار شما قرار دهد. مانند دیتابیس Postgress و API و Authentication و غیره…
بنابراین Supabase می تواند بعنوان BaaS یا Backend as a Service برای پروژه های فرانتی شما مورد استفاده قرار گیرد. و شما قادر خواهید بود فقط بر روی بخش فرانت پروژه های خود تمرکز کنید و درگیر توسعه backend و database و authentication و سایر مسائل نشوید.
در ادامه مقاله به معرفی Supabase و نحوه پیکربندی آن خواهیم پرداخت. پس از یادگیری این سرویس، در زمان، هزینه و انرژی خود در توسعه پروژه های فول استک صرفه جویی خواهید کرد.
امکانات و ویژگی های Supabase:
در طی سالهای گذشته، فایربیس (Firebase) محبوب ترین و معروف ترین BaaS یا بکند بعنوان سرویس بوده است. اما اخیرا سرویس Supabase بسیار موفق طاهر شده و ظاهرا می تواند جایگزین خوبی برای Firebase باشد.
بزرگترین مزیت Supabase متن باز (open source) بودن آن است. در واقع supabase به شما این امکان را می دهد تا کد خود را هر جا که دلتون خواست deploy کنید. هم می توانید روی سرورهای خود Supabase دپلوی کنید و هم روی سرورهای دلخواه خود. یکی از کاربردهای این مزیت اینست که از vendor lock-in جلوگیری می کند. به این معنی که بطور مثال اگر شرکت هاستینگ شما هزینه سرویس دهی خود را بشدت افزایش دهد با استفاده از Supabase شما به راحتی خواهید توانست از سرویس شرکت دیگری استفاده کنید و این جابجایی امکان پذیر است. اما اگر از سرویس هایی مانند فایربیس -FireBase- استفاده کرده باشید این جابجایی براحتی انجام نخواهد شد.
ویژگی دیگری که Supabase به توسعه دهندگان ارائه می دهد دیتابیس Postgress می باشد که با تمام نسخه های کتابخانه React.js سازگار است. حتی با سایر کتابخانه ها و فریم ورک های جاوا اسکریپتی دیگر (مانند Angular) نیز Compatible می باشد.
نصب سرویس Supabase توسط npm:
به منظور نصب Supabase روی پروژه خود می توانید از دستور npm به شکل زیر استفاده کنید:
npm i @supabase/supabase-js
همانطور که در تصویر زیر مشاهده می کنید، در تاریخ نگارش مقاله، نسخه 2.1.3 از سرویس Supabase ارائه شده است و بطور هفتگی بیش از 76 هزار دانلود دارد.
ایجاد پروژه جدید و تنظیمات آن:
برای شروع کار با Supabase ابتدا باید API و Database را ایجاد کنیم. مراحل زیر را انجام دهید:
- به مسیر app.supabase.com رفته و گزینه “New Project” را کلیک کنید.
- مشخصات دیتابیس موردنظر را وارد کنید و منتظر لانچ شدن دیتابیس جدید باشید.
ایجاد Database Schema:
پس از تعریف دیتابیس، نوبت به ایجاد schema برای پایگاه داده است. به این منظور می توان از ویژگی “User Management Starter” در SQL Editor استفاده کرد:
- در داشبورد Supabase وارد صفحه SQL Editor شوید.
- روی گزینه “User Management Starter” کلیک کنید.
- روی Run کلیک کنید.
به ویدیوی کوتاه زیر در این زمینه توجه کنید:
روش بعدی برای ایجاد Database Schema اینست که دستورات SQL زیر را کپی کرده و در محیط sql داشبورد پیست کرده و اجرا کنید:
-- Create a table for public profiles create table profiles ( id uuid references auth.users not null primary key, updated_at timestamp with time zone, username text unique, full_name text, avatar_url text, website text, constraint username_length check (char_length(username) >= 3) ); -- Set up Row Level Security (RLS) -- See https://supabase.com/docs/guides/auth/row-level-security for more details. alter table profiles enable row level security; create policy "Public profiles are viewable by everyone." on profiles for select using (true); create policy "Users can insert their own profile." on profiles for insert with check (auth.uid() = id); create policy "Users can update own profile." on profiles for update using (auth.uid() = id); -- This trigger automatically creates a profile entry when a new user signs up via Supabase Auth. -- See https://supabase.com/docs/guides/auth/managing-user-data#using-triggers for more details. create function public.handle_new_user() returns trigger as $$ begin insert into public.profiles (id, full_name, avatar_url) values (new.id, new.raw_user_meta_data->>'full_name', new.raw_user_meta_data->>'avatar_url'); return new; end; $$ language plpgsql security definer; create trigger on_auth_user_created after insert on auth.users for each row execute procedure public.handle_new_user(); -- Set up Storage! insert into storage.buckets (id, name) values ('avatars', 'avatars'); -- Set up access controls for storage. -- See https://supabase.com/docs/guides/storage#policy-examples for more details. create policy "Avatar images are publicly accessible." on storage.objects for select using (bucket_id = 'avatars'); create policy "Anyone can upload an avatar." on storage.objects for insert with check (bucket_id = 'avatars'); create policy "Anyone can update their own avatar." on storage.objects for update using (auth.uid() = owner) with check (bucket_id = 'avatars');
دریافت API Keys:
اکنون توانسته اید چند جدول در دیتابیس تعریف کنید. حالا وقت آنست که توسط auto-generated API تعدادی دیتا وارد این جداول کنیم. فقط کافبست URL و anon key را از API Setting دریافت کنیم. مراحل زیر را طی کنید:
- وارد صفحه تنظیمات (Setting) در داشبورد شوید.
- روی API در سایدبار کلیک کنید.
- آیتم های URL و anon key و service_role را در این صفحه پیدا کنید.
به ویدیوی کوتاه زیر توجه کنید:
توسعه اپلیکیشن React و نصب Supabase:
حالا نوبت به توسعه وب اپلیکیشن React.js رسیده است!
می توان با استفاده از دستور Create React App، اپلیکیشن ری اکت را ایجاد کرد. برای مثال، ما نام این پروژه را supabase-react قرار دادیم:
npx create-react-app supabase-react cd supabase-react
سپس باید تنها پکیج این پروژه را نصب کنیم. یعنی supabase.js
npm install @supabase/supabase-js #or yarn add @supabase/supabase-js
در مرحله بعد باید یک فایل env. بسازید و متغیرهای محیطی یا environmental variables را در آن به شکل زیر ذخیره کنید:
REACT_APP_SUPABASE_URL=YOUR_SUPABASE_URL REACT_APP_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
در فایل مذکور باید URL و anon key را که در مراحل قبل بدست آوریم درج شوند.
حالا باید یک helper file بسازیم که به عنوان راه اتداز اولیه Supabase client عمل کند. در فولدر src پروژه ری اکت خود فایلی بنام supabaseClient.js تعریف کنید و کد زیر را به ان اضافه کنید:
import { createClient } from '@supabase/supabase-js' const supabaseUrl = process.env.REACT_APP_SUPABASE_URL const supabaseAnonKey = process.env.REACT_APP_SUPABASE_ANON_KEY export const supabase = createClient(supabaseUrl, supabaseAnonKey)
مرحله اختیاری: اگر بخواهید اپلیکیشن شما ظاهر کاربرپسندی داشته باشد، کافیست این استایل ها را در فایل src/index.css درج کنید.
تعریف کامپوننت لاگین (Login):
در این بخش می خواهیم کامپوننت های مربوط به sign in و sign up کاربران را ایجاد کنیم. کاربران در روش زیر می توانند بدون ورود رمز عبور و فقط با ارائه آدرس ایمیل، لاگین و رجیستر کنند. پس در فولدر src و در فایل Auth.js کد زیر را درج کنید:
import { useState } from 'react' import { supabase } from './supabaseClient' export default function Auth() { const [loading, setLoading] = useState(false) const [email, setEmail] = useState('') const handleLogin = async (e) => { e.preventDefault() try { setLoading(true) const { error } = await supabase.auth.signInWithOtp({ email }) if (error) throw error alert('Check your email for the login link!') } catch (error) { alert(error.error_description || error.message) } finally { setLoading(false) } } return ( <div className="row flex-center flex"> <div className="col-6 form-widget" aria-live="polite"> <h1 className="header">Supabase + React</h1> <p className="description">Sign in via magic link with your email below</p> {loading ? ( 'Sending magic link...' ) : ( <form onSubmit={handleLogin}> <label htmlFor="email">Email</label> <input id="email" className="inputField" type="email" placeholder="Your email" value={email} onChange={(e) => setEmail(e.target.value)} /> <button className="button block" aria-live="polite"> Send magic link </button> </form> )} </div> </div> ) }
ایجاد صفحه اکانت (Account):
در مرحله بعد، می خواهیم این امکان را به کاربران لاگین شده بدهیم تا اطلاعات خود را در صفحه اکانت مشاهده و مدیریت کنند. به این منظور، یک فایل بنام Account.js در فولدر src بسازید:
import { useState, useEffect } from 'react' import { supabase } from './supabaseClient' const Account = ({ session }) => { const [loading, setLoading] = useState(true) const [username, setUsername] = useState(null) const [website, setWebsite] = useState(null) const [avatar_url, setAvatarUrl] = useState(null) useEffect(() => { getProfile() }, [session]) const getProfile = async () => { try { setLoading(true) const { user } = session let { data, error, status } = await supabase .from('profiles') .select(`username, website, avatar_url`) .eq('id', user.id) .single() if (error && status !== 406) { throw error } if (data) { setUsername(data.username) setWebsite(data.website) setAvatarUrl(data.avatar_url) } } catch (error) { alert(error.message) } finally { setLoading(false) } } const updateProfile = async (e) => { e.preventDefault() try { setLoading(true) const { user } = session const updates = { id: user.id, username, website, avatar_url, updated_at: new Date(), } let { error } = await supabase.from('profiles').upsert(updates) if (error) { throw error } } catch (error) { alert(error.message) } finally { setLoading(false) } } return ( <div aria-live="polite"> {loading ? ( 'Saving ...' ) : ( <form onSubmit={updateProfile} className="form-widget"> <div>Email: {session.user.email}</div> <div> <label htmlFor="username">Name</label> <input id="username" type="text" value={username || ''} onChange={(e) => setUsername(e.target.value)} /> </div> <div> <label htmlFor="website">Website</label> <input id="website" type="url" value={website || ''} onChange={(e) => setWebsite(e.target.value)} /> </div> <div> <button className="button primary block" disabled={loading}> Update profile </button> </div> </form> )} <button type="button" className="button block" onClick={() => supabase.auth.signOut()}> Sign Out </button> </div> ) } export default Account
آپدیت فایل App.js و اجرای برنامه:
برای ادامه کار و اجرای اپلیکیشن، نیاز است تغییرات زیر را در فایل App.js ایجاد کنید:
import './index.css' import { useState, useEffect } from 'react' import { supabase } from './supabaseClient' import Auth from './Auth' import Account from './Account' export default function App() { const [session, setSession] = useState(null) useEffect(() => { supabase.auth.getSession().then(({ data: { session } }) => { setSession(session) }) supabase.auth.onAuthStateChange((_event, session) => { setSession(session) }) }, []) return ( <div className="container" style={{ padding: '50px 0 100px 0' }}> {!session ? <Auth /> : <Account key={session.user.id} session={session} />} </div> ) }
و برای اجرای برنامه، مانند سایر اپلیکیشن های ری اکتی، دستور زیر را اجرا کنید:
npm start #or yarn start
خروجی برنامه در مسیر localhost:3000 قابل مشاهده خواهد بود:
امکان آپلود تصویر پروفایل:
برای هر پروژه Supabase یک فضای ذخیره سازی (Storage) اختصاص داده می شود که می تواند فایل های حجیم مانند تصاویر یا ویدیوها را در بر گیرد. در ادامه می خواهیم یک کامپوننت بسازیم تا کاربران بتوانند تصویر موردنظر خود را به عنوان آواتار پروفایل خود آپلود کنند. یک فایل بنام Avatar.js در فولدر src تعریف کرده و کدهای زیر را در آن درج کنید:
import { useEffect, useState } from 'react' import { supabase } from './supabaseClient' export default function Avatar({ url, size, onUpload }) { const [avatarUrl, setAvatarUrl] = useState(null) const [uploading, setUploading] = useState(false) useEffect(() => { if (url) downloadImage(url) }, [url]) const downloadImage = async (path) => { try { const { data, error } = await supabase.storage.from('avatars').download(path) if (error) { throw error } const url = URL.createObjectURL(data) setAvatarUrl(url) } catch (error) { console.log('Error downloading image: ', error.message) } } const uploadAvatar = async (event) => { try { setUploading(true) if (!event.target.files || event.target.files.length === 0) { throw new Error('You must select an image to upload.') } const file = event.target.files[0] const fileExt = file.name.split('.').pop() const fileName = `${Math.random()}.${fileExt}` const filePath = `${fileName}` let { error: uploadError } = await supabase.storage.from('avatars').upload(filePath, file) if (uploadError) { throw uploadError } onUpload(filePath) } catch (error) { alert(error.message) } finally { setUploading(false) } } return ( <div style={{ width: size }} aria-live="polite"> <img src={avatarUrl ? avatarUrl : `https://place-hold.it/${size}x${size}`} alt={avatarUrl ? 'Avatar' : 'No image'} className="avatar image" style={{ height: size, width: size }} /> {uploading ? ( 'Uploading...' ) : ( <> <label className="button primary block" htmlFor="single"> Upload an avatar </label> <div className="visually-hidden"> <input type="file" id="single" accept="image/*" onChange={uploadAvatar} disabled={uploading} /> </div> </> )} </div> ) }
اکنون برای اینکه بتوان در صفحه اکانت، قابلیت آپلود آواتار را داشته باشیم، باید تغییرات زیر را در فایل Account.js اعمال کنید:
// Import the new component import Avatar from './Avatar' // ... return ( <div className="form-widget"> {/* Add to the body */} <Avatar url={avatar_url} size={150} onUpload={(url) => { setAvatarUrl(url) updateProfile({ username, website, avatar_url: url }) }} /> {/* ... */} </div> )
امیدوارم تا اینجای آموزش استفاده کافی را برده باشید. این مقاله به زودی آپدیت خواهد شد و نحوه احراز هویت را به روش های مختلف آموزش خواهیم داد. پس با آکادمی راهکارینو همراه باشید…
دیدگاهتان را بنویسید