Supabaseのstorageを使用して、アバターを表示させてみた

2022.04.30

こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。

supabaseとは、firebaseの大替サービスとも言われるBaasです。firebaseとの大きな違いは、データベースにRDBを採用していることです。

今回は、supabaseのstorage機能を使用して、Next.jsのプロジェクトに画像を表示させてみました。

supabase側の設定

supabaseにログインし「New project」からプロジェクトを新規で作成します。

サイドバーのStorageから「create a new bucket」を選択します。

名前を入力し「public Bucket」にチェックをつけて、バケットを作成します。今回は、公式と同じ「avatars」という名前にしました。

作成したbucketを指定し、左上の「Upload file」からファイルをアップロードします。

Settings内の「Policies」を選択し、ポリシーを定義します。ここで、細かい権限を追加することができます。今回は「Policies under storage.buckets 」を変更します。

ポリシーのテンプレートがあるようなので、こちらを使います。

一番上の「Enable read access to everyone」を選択します。

以下のように変更して、ポリシーを追加します。

supabase側の設定は、以上です。

Next.js側の設定

では、Next.jsのプロジェクトを作成して、コードを記述していきましょう。

プロジェクト作成

$ yarn create next-app --ts

$ cd <appName>

supabaseをインストールします。

$ yarn add  @supabase/supabase-js

.env.localファイルを作成し、キーとURLを環境変数に保存します。 キーとURLはsupabaseの「Settings」→「API」から確認することができます。

.env.local

NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY

/libsフォルダを作成し、配下にsupabaseClient.tsファイルを作成します。

supabaseClient.tsを以下のように記述し、Clientを初期化します。

/libs/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;

if (!supabaseUrl || !supabaseAnonKey) {
  throw new Error("");
}
export const supabase = createClient(supabaseUrl, supabaseAnonKey);

では、index.tsxで画像を表示できるよう変更します。 今回、画像のURLを取得するgetPublicUrl()と、バケットの情報を取得するgetBucket()を使用しました。

/page/index.tsx

import type { GetServerSideProps } from "next";
import Head from "next/head";
import Image from "next/image";
import { FC, useEffect } from "react";
import { supabase } from "../libs/supabaseClient";
import styles from "../styles/Home.module.css";

type Props = {
  url: string;
};

export const getServerSideProps: GetServerSideProps = async () => {
  // 画像の名前を指定
  const { publicURL } = supabase.storage
    .from("avatars")
    .getPublicUrl("avatar.JPG");

  return {
    props: {
      url: publicURL,
    },
  };
};

const Home: FC<Props> = (props) => {
  const getBucket = async () => {
    const { data, error } = await supabase.storage.getBucket("avatars");

    console.log(data);
  };

  useEffect(() => {
    getBucket();
  }, []);

  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}>
        <h1 className={styles.title}>supabase Storage</h1>

        <p className={styles.description}>Get My Avatar!</p>

        {props.url ? (
          <Image
            src={props.url}
            alt="Avatar"
            width="200"
            height="200"
            style={{ borderRadius: "50%" }}
          />
        ) : (
          <div
            className="avatar no-image"
            style={{ height: "200px", width: "200px", borderRadius: "50%", background: "gray" }}
          />
        )}
      </main>

      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{" "}
          <span className={styles.logo}>
            <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
          </span>
        </a>
      </footer>
    </div>
  );
};

export default Home;

supabaseから画像を取得するため、next.config.jsに外部ドメインを設定します。

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  images: {
    domains: ["ドメインURL"],
  },
};

module.exports = nextConfig

開発環境を立ち上げて、確認します。

$ yarn dev

うまくいっていれば、アバターが表示されているはずです。

また、バケットの情報もログに出力されています。

まとめ

簡単にですが、supabaseのstorage機能を使ってみました。supabaseは勢いのあるサービスの一つですので、今後はfunctionsなどの他の機能を試してみようと思います。

ではまた。