React × Supabase × Vercel シリーズ
ある程度、独立した内容になっていますが、ご興味あればどうぞ 💁♂️
- ① 作ってデプロイ編 ← 本記事
- ② Vitest で単体テスト編
- ③ GitHub Actions で CI/CD 編
はじめに
旧 Twitter 新 X を見てる感じ、個人開発をしている人は Supabase と Vercel をよく使っているイメージがあります。
個人でサクッと Web アプリを作りたいなら、こいつらを採用すると良いのか? 🤔
TODO アプリを題材にして、実際に Supabase と Vercel を触ってみようのシリーズです ✊
フロントエンドは React で書きました。
Supabase, Vercel って? 🤔
どちらも 無料枠があります!
とてもうれしいですね ☺️
Supabase
Firebase の代替として注目されているオープンソースの BaaS (Backend as a Service)
PostgreSQL ベースの RDB や認証機能などが使えます。サーバレス API も作れます。
Vercel
フロントエンドの Web アプリを簡単にデプロイ・ホスティングできるプラットフォームサービス
GitHub などのバージョン管理ツールと連携して、push するだけで自動でデプロイ(CI/CD) してくれます。
プルリクエストごとに自動でプレビュー環境を作るとかもできます。
成果物 🏁
ディレクトリ構成
typescript-todo
├── README.md
└── todo-app
├── README.md
├── eslint.config.js
├── index.html
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ │ └── react.svg
│ ├── components
│ │ ├── CreateTodoForm
│ │ │ ├── CreateTodoForm.css
│ │ │ └── CreateTodoForm.tsx
│ │ ├── TodoListItem
│ │ │ ├── TodoListItem.css
│ │ │ └── TodoListItem.tsx
│ │ └── ValueViewer
│ │ ├── ValueViewer.css
│ │ └── ValueViewer.tsx
│ ├── hooks
│ │ └── useTodo.ts
│ ├── index.css
│ ├── lib
│ │ └── supabaseClient.ts
│ ├── main.tsx
│ ├── pages
│ │ └── TodoHome
│ │ ├── TodoHome.css
│ │ └── TodoHome.tsx
│ ├── types
│ │ └── Todo.ts
│ ├── utils
│ │ ├── TodoUtil.test.ts
│ │ ├── TodoUtil.ts
│ │ └── api.ts
│ └── vite-env.d.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.node.json
├── vite.config.ts
└── vitest.config.ts
作り方 🔨
1. プロジェクトのセットアップ
お馴染みのおまじない 🪄
ビルドツールには Vite を使っています。
npm create vite@latest todo-app --template react-ts
cd todo-app
npm install
create-react-app
は公式で非推奨となりました。
https://github.com/facebook/create-react-app/pull/17003
2. Supabase プロジェクトの作成とテーブル設計
Supabase にログインして、新しいプロジェクトを作成します 🚀
テーブル設計
テーブル名: todos
カラム構成は以下の通り
カラム名 | 型 | 属性 |
---|---|---|
id | int8 | Primary Key, AutoIncrement |
text | text | not null |
done | bool | default false |
created_at | timestamptz | default now() |
updated_at | timestamptz | default now() |
updated_at
は UPDATE の度に現在時刻で更新したいので、SQL Editor で以下のクエリを実行します。
create extension if not exists moddatetime schema extensions;
create trigger handle_updated_at before update on todos
for each row execute procedure moddatetime (updated_at);
デフォルトで RLS(Row Level Security)が有効なはずなので、RLS Policy を作成する必要があります。
"Add RLS Policy" をポチッ
"Create Policy" もポチッと押して
以下のようなポリシーを追加しましょう 💁♂️
3. Supabase クライアントの設定
Supabase と接続するのに必要なパッケージをインストール
npm install @supabase/supabase-js
開発環境用に .env.local
を用意し、環境変数を定義します。
VITE_SUPABASE_URL=https://xxx.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
この子たちは Settings > Data API で確認できます 👀
クライアントインスタンス supabaseClient
を作ります。
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL as string;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY as string;
export const supabaseClient = createClient(supabaseUrl, supabaseAnonKey);
4. CRUD 処理の実装
超シンプルな CRUD です。
import { supabaseClient } from '../lib/supabaseClient';
import { Todo } from '../types/Todo';
const supabase = supabaseClient;
export class TodoApi {
async readItems(): Promise<Todo[]> {
const { data, error } = await supabase
.from('todos')
.select('id, text, done')
.order('id', { ascending: false });
if (error) throw error;
return data as Todo[];
}
async createItem(item: Omit<Todo, 'id'>) {
const { error } = await supabase.from('todos').insert(item);
if (error) throw error;
}
async updateItem(item: Todo) {
const { error } = await supabase
.from('todos')
.update(item)
.eq('id', item.id);
if (error) throw error;
}
async deleteItem(id: number) {
const { error } = await supabase.from('todos').delete().eq('id', id);
if (error) throw error;
}
}
5. React アプリの実装
割愛。リポジトリ見てください 🙇♂️
実装が終わったら GitHub に push しておきます。
開発サーバーは npm run dev
で起動します。
6. Vercel にデプロイ
Vercel にログインして、新しいプロジェクトを作成します 🚀
以下のように設定してデプロイ!
ここで設定している環境変数は、本番環境用です。
開発環境と本番環境で DB を分けたい場合は、それぞれ別の Supabase プロジェクトを作ってください。
デプロイ成功しました 🎉
実際、作ったアプリがデプロイされていました ✌️
CI/CD
デプロイしているブランチに変更を push すると、Vercel は自動で再デプロイしてくれます。
試しに、タイトル部分を赤字にしてみます。
<h1>Todo</h1>
h1 {
font-size: 2em;
+ color: red;
}
赤くなりました!
おわりに
めちゃくちゃ簡単!
Vercel では最小構成の CI/CD も提供されていて、非常に便利だなと思いました。
テストを pass したときだけデプロイしたい場合には、GitHub Actions などで CI/CD パイプラインを構築する必要があるようです。
チャレンジしてみます ✊