VS Code の Remote Containers を使って Supabase を簡単にローカル開発する
ほぼ一年前に Supabase を使ったサンプルアプリ作成の記事を投稿しました。
- Supabase をローカルで立ち上げて React から使ってみる 〜 Redux Toolkit と React Router を用いた認証編 〜
- Supabase の Slack クローンアプリのサンプルを TypeScript & Redux Toolkit & React Router で書き換える(Supabase Database の操作)
それ以降ほとんど Supabase を触る機会がなく放置していましたが、
Realtime 機能の Postgres RLS 対応とか、いつの間にか出ていた Edge Funtction とか、
進化した CLI とか色々変化があったようなので、改めて記事を書いていきたいと思います。
今回のコンセプト
今回は VSCode の拡張機能「Remote - Containers」の中で Supabase を起動してローカルで開発できるようにする方法を試してみます。
Prerequisites
以下をインストールしてください
- Docker
- Vs Code
- Vs Code の拡張機能 Remote - Containers
Next.js アプリの作成
Next.js でアプリケーションを作成していきます。
また、TypeScript を利用するのでオプションつきで以下のようにコマンドを実行します。
npx create-next-app@latest --typescript
プロジェクト名の入力を求められますが、なんでも構いません。
Remote - Containers の設定
Remote Containers の設定を行なっていきます。
VS Code を開き[Ctrl (Mac は Cmd) + Shift + P]でコマンドパレットを開き、
remote containers add
と入力して以下の画像の項目を選択
Show All Definitions...を選択
Node.js & TypeScript を選択
default (16-bullseye) を選択
Docker-in-Docker と Git を選択
Docker Engine と Git のバージョンは latest を選択
全て選択して OK を押すと.devcontainer
フォルダが作成されます。
Remote Container の設定に Post Create Command を追加
次に Supabase CLI をインストールできるように Post Create Command の設定を行います。
こちらに手動でインストールする場合の方法がありますのでこれを参考にします。
.devcontainer
フォルダにpostCreateCommand.sh
というファイルを作成して次の内容を貼り付けてください。
./.devcontainer/postCreateCommand.sh
#!/bin/sh
set -ex
# Supabase CLI
# Select a package that is suitable for your environment from <https://github.com/supabase/cli/releases>
# The package below is for the Apple Silicon Mac.
curl -LO https://github.com/supabase/cli/releases/download/v0.39.3/supabase_0.39.3_linux_arm64.deb
sudo dpkg -i ./supabase_0.39.3_linux_arm64.deb
rm -rf supabase_0.39.3_linux_arm64.deb
supabase init
# NPM
npm install
echo "Done!"
このページによると Dev Containers typescript-node
のコンテナ OS は Debian ですので、curl
でダウンロードするのは Debian 用のパッケージです。
私の PC は M1 Macbook Air なので、arm64
を選択していますが、
こちらのリリース一覧からご自身の環境にあったものを選択するようにしてください。
次にこのスクリプトを呼び出せるように設定します。
.devcontainer/devcontainer.json
を開き以下を追加します。
{
"postCreateCommand": "chmod +x ./.devcontainer/postCreateCommand.sh && ./.devcontainer/postCreateCommand.sh"
}
以上が設定できたら、画面左下のこのマーク
をクリックして、Reopen in Container
を選択し開発環境のコンテナを起動します。
暫く時間がかかりますが、エラーなく立ち上がれば OK です!
Supabase のローカル起動
Dev Container の設定がうまくいっていれば、
Supabase をローカルで起動する環境が整っていると思います。
次のコマンドを実行して、Supabase をローカル起動します。
supabase start
今後、Dev Container を起動し直した場合にはsupabase start
をし直してください。
supabase start
して暫くすると、以下のように Supabase が起動します。
Started supabase local development setup.
API URL: http://localhost:54321
DB URL: postgresql://postgres:postgres@localhost:54322/postgres
Studio URL: http://localhost:54323
Inbucket URL: http://localhost:54324
anon key: eyJhbGci...
service_role key: eyJhbGci...
それぞれの項目の意味ですが、
- API URL: Supabase URL
- DB URL: Postgres Database の URL
- Studio: Studio URL(<app.supabase.com>と同じような GUI ツール)
- Inbucket: Emailbox(メール送信)
- anon key: Supabase の API を呼び出すためのキー。ブラウザで使っても良い。
- service_role key: Supabase の API を呼び出すためのキー。ブラウザで使ってはいけない。
といった内容です。
anon key と service_role key は本番環境では上記のように使い分ける必要があります。
service_role key を使うと全て管理者権限で実行されるイメージですので注意が必要です。
今回はローカル開発なので特に気にする必要はありません。
また、localhost:54323
をブラウザで開くと Studio というものにアクセスでき、
以下の画像のように<app.supabase.com>と同じような GUI でプロジェクト管理を行えます。
Supabase を停止する場合は
supabase stop
を実行してください。
Next.js アプリケーションの作成
環境が整いましたので、実際にアプリケーションを作成していきます。
まず、環境変数を設定します。
.env.local
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOi...
NEXT_PUBLIC_SUPABASE_URL
にはsupabase start
を実行したときに表示されたAPI URL
の値を、
NEXT_PUBLIC_SUPABASE_ANON_KEY
にはanon key
の値を設定してください。
次に、必要なモジュールをインストールします。
npm install @supabase/supabase-js
ここで、一度 Dev Server を起動しておきます。
次のコマンドを実行してください。
npm run dev
このような画面が表示されれば OK です。
Supabase client の作成
では、Next.js を編集していきます。
まず、Supabase client を作成するためのヘルパーモジュールを定義します。
./utils/supabaseClient.ts
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);
Components の作成
次に表示するコンポーネントを作成します。
ログインを行うAuth
コンポーネントと
ログイン後に表示する画面Dashboard
コンポーネントを作成します。
./components/Auth.tsx
import React, { useState } from "react";
import { supabase } from "../utils/supabaseClient"; // ①
export const Auth: React.FC = () => {
const [loading, setLoading] = useState(false);
const [email, setEmail] = useState("");
const handleLogin = async (email: string) => {
try {
setLoading(true);
const { error } = await supabase.auth.signIn({ email }); // ②
if (error) throw error;
alert("Check your email for the login link!");
} catch (error) {
if (error instanceof Error) {
alert(error.message);
}
} finally {
setLoading(false);
}
};
return (
<div>
<h1>Sign in</h1>
<div>
<input
type="email"
placeholder="Your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<button
onClick={(e) => {
e.preventDefault();
handleLogin(email);
}}
disabled={loading}
>
<span>{loading ? "Loading" : "Send magic link"}</span>
</button>
</div>
</div>
);
};
① で先ほど作った Supabase Client をインポートし、② で email にログインリンクが送られるようにしています。
./components/Dashboard.tsx
import React from "react";
import { Session } from "@supabase/supabase-js";
type Props = {
session: Session;
};
export const Dashboard: React.FC<Props> = ({ session }) => {
return (
<div>
<h1>Hello, {session.user?.email}</h1>
Dashboard
</div>
);
};
Supabase のログインセッションをプロパティとして受け取るようにしています。
このコンポーネントはひとまずメールアドレスを表示するだけです。
アプリケーションの起動
では最後にコンポーネントを表示できるように設定し、アプリケーションを起動します。
./pages/index.tsx
import type { NextPage } from "next";
import Head from "next/head";
import { useEffect, useState } from "react";
import styles from "../styles/Home.module.css";
import { Session } from "@supabase/supabase-js";
import { supabase } from "../utils/supabaseClient";
import { Auth } from "../components/Auth";
import { Dashboard } from "../components/Dashboard";
const Home: NextPage = () => {
const [session, setSession] = useState<Session | null>();
useEffect(() => {
setSession(supabase.auth.session());
supabase.auth.onAuthStateChange((_event, session) => {
setSession(session);
});
}, []);
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<div>{!session ? <Auth /> : <Dashboard session={session} />}</div>
</main>
</div>
);
};
export default Home;
これで完成です。
先ほど開発サーバーは起動しているので、ページをリロードしてください。
(起動していない場合はnpm run dev
を実行)
すると以下のような Sign In 画面が表示されるはずです。
何かメールアドレス(test@example.comなど存在しないアドレスも可)を入力して、
Send magic link
ボタンをクリックします。
すると画面上部にCheck your email for the login link!
と書かれたアラートが表示されます。
これでログイン用のマジックリンクが送信されているはずですので、メールボックスを確認します。
ここで開くのは Gmail などではなく、supabase start
を実行した時に表示された、Inbucket URL
のリンクです。
設定を特に変えていなければhttp://localhost:54324
のはずです。
以下のような画面が開くので、右上の入力ボックスに先ほどのメールアドレスを入力すると、
受信メールの一覧が開きます。
このメールに記載された、Log in
リンクをクリックし、以下のように Dashboard が表示されれば成功です。
Studio を確認する
ユーザーデータができているか確認します。
supabase start
を実行した際に表示された、Studio URL
を開きます。
設定を変えていなければ、http://localhost:54323
のはずです。
Studio が表示されたら、Default Project を選択し、
左のドロワーから Authentication をクリックすると以下のようにユーザーが登録されているのが確認できます。
まとめ
今回は VS Code の Remote Containers 拡張機能を利用して、コンテナ内で Supabase アプリを作成してみました。
Remote Container を利用すると、チームメンバー間で開発環境を揃えるのが簡単になったり、
マシンの環境を汚さずに環境構築ができたりと利点が大きいですね!
Supabase が Remote Container で動かせることがわかったので、
今後個人で簡単なアプリケーションを作るのも捗りそうです。
今回は環境構築のみでしたが、次回以降はこの環境で Realtime や Edge Function の機能も試してみる予定です。