🐟

Vercelに構築したNext.js*Supabaseの環境をローカルにも構築する

2025/03/09に公開

BaaS便利だけど

Next.jsを書いてみつつ、Supabaseとの連携やVercelでのデプロイについて学んでいます。段階を踏んで勉強していきたい私のような初学者にとって、Supabaseのような無料枠のあるBaaS(Backend as a Service)は非常に便利です。

一方、ローカルですべてが完結する技術に比べると、開発初期の環境構築が少し難しい(イメージしにくい)という弱点もあります。今回は、オンラインのSupabase環境が構築できたと仮定して、ローカルの構築を行っていきます。

前提条件

最小構成のNext.jsアプリをVercelのテンプレートで作成し、Githubに自動でInitial commit、Supabaseと紐づけるところまで完了しました。デプロイURLをクリックするとデモアプリが表示される状態からスタートです。

手順

1. Supabaseのインストール

初っ端から引用で恐縮ですが、npx supabase init まではこれを参考にやってみました。

↓ 参考にさせていただいた記事

Supabaseをローカル環境に構築してNext.jsアプリで利用する(前半)

紆余曲折をへて初期化まで完了します。

2. Supabaseの起動

次に、Supabaseの起動を試みます。しかし、npx supabase start を実行しようとするとhealthcheckの段階でerrorが出て停止してしまいます。

supabase_vector_project container is not ready: unhealthy というerrorです。

↓ 参考にさせていただいた記事

意外とネットに情報がないSupabaseの困りごとメモ(2024/10/14現在) - Qiita

根本的な解決策ではないようですが、以下のようにconfig.tomlを編集すればよいとのこと。

[analytics]
- enabled = true
+ enabled = false
port = 54327
backend = "postgres"

⇒ これを行うことで、SupabaseのAPIURLなどが取得できました。

3. テーブルを追加する(オンライン)

次に、Supabaseにテーブルを作成していきます。ここでは試しにメモアプリを作成します。メモ内容を保持する「notes」というテーブルを作成し、以下のような構成とします。

ソースは以下の通り、2つに分けて記載します(クライアントサイドの処理は分離させて書く必要があります)。

// app\page.tsx
import NoteForm from './components/NoteForm';

export default function Home() {
  return <NoteForm />;
}
// app\components\NoteForm.tsx
"use client";

import { createClient } from '@supabase/supabase-js';
import { useState } from 'react';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || '';
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || '';

const supabase = createClient(supabaseUrl, supabaseAnonKey);

export default function NoteForm() {
  const [message, setMessage] = useState('');
  const [error, setError] = useState('');

  // メモを登録する関数
  const addNote = async (content: string) => {
    try {
      setMessage('');
      setError('');
      
      console.log('Supabase URL:', supabaseUrl);
      console.log('Adding note with content:', content);
      
      const { data, error } = await supabase
        .from('notes')
        .insert([{ content }]);

      if (error) {
        console.error('Error adding note:', error);
        setError(`エラー: ${error.message}`);
      } else {
        console.log('Note added:', data);
        setMessage('メモが追加されました!');
      }
    } catch (e) {
      console.error('Exception:', e);
      setError(`例外が発生しました: ${e instanceof Error ? e.message : String(e)}`);
    }
  };

  return (
    <div className="p-4">
      <h1 className="text-xl font-bold mb-4">メモアプリ</h1>
      
      <button 
        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
        onClick={() => addNote('新しいメモ')}
      >
        Add Note
      </button>
      
      {message && <p className="mt-2 text-green-600">{message}</p>}
      {error && <p className="mt-2 text-red-600">{error}</p>}
    </div>
  );
} 

4. テーブルを追加する(ローカル)

ネット記事には「SQLをエクスポートしてきましょう」との記載。オンライン版のSupabaseには確かにエクスポートボタンはありました。しかし、このままdb push しても何も起こりません(そりゃそうだ)。

↓ 参考にさせていただいた記事

5分でわかる!Supabase CLIを使いこなすための開発フロー

調べると、ローカルのSupabaseを扱えるGUIの「Supabase Studio」なるものが存在しており、こっちを使うことが明らかになりました。

Supabase Studio

Supabase studioでテーブルを作成し、

npx supabase db dump --local -f supabase/schema.sql を実行すると、

schema.sql の79行目にテーブルの定義が作成されていました。

CREATE TABLE IF NOT EXISTS "public"."notes" (
    "id" bigint NOT NULL,
    "created_at" timestamp with time zone DEFAULT "now"() NOT NULL,
    "content" "text"
);

続いて、型定義ファイルの作成です。

ルートディレクトリにtypes\supabase.tsを作成し、

npx supabase gen types typescript --local > types/supabase.tsを実行しました。

5. テーブルへのアクセス権限

Notesテーブルにアクセス(特にinsert)するためには、あらかじめPolicyの設定を行っておく必要があります。設定はアクションやparamsを指定して行うことができます。

Supabase Studioを開いて、左側のペインから「Authentication」を選択、「CONFIGRATION」からnotesの「Create policy」を選びます。

設定画面の右側に現れるTemplateの「Insert」を選び、「Target roles」を「Default」にすればOKです。改めてnpm run devを実行すると、無事にメモアプリが動作するようになりました。

↓ 参考にさせていただいた記事

next.jsとsupabaseでRow Level Securityを使用して権限による抽出をおこなってみた - Qiita

以上の対応をし、無事Noteテーブルにメモ情報を持ったメモアプリができました。

(最後に)デプロイしてみる

メモアプリをVercelでデプロイしてみます。おうち(クラウド)に帰るまでが遠足(ローカル環境構築)です。まずはgitignoreを見直して、環境変数やschema.sqlを追跡から外します。

コミットすると、自動的にデプロイが始まりましたが、エラー。と思ったら、環境変数が入っていないだけでした。慌てて環境変数を入れなおしてredeployすると、無事メモアプリが立ち上がりました。

Discussion