あるWebサービスの開発メモ・Docker + Nextjs + TypeScript + mui + supabase-js + react-query + swiper の導入手順

- [あるWebサービスの開発メモ・目次ページに戻る](https://qiita.com/ishi32/items/152a1ecf7eeee7a8fb57)

## Github

まずは Github に新規リポジトリをつくります。「Github なんか使わないよ」という方は、Vercel へのデプロイが git push をトリガーにしているのでぜひ導入を検討してみてください。

![スクリーンショット 2022-08-12 9.40.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/8afa5fee-d5f0-358d-8801-8886a414e2e6.png)

- [Create repository]

クライアントPCで clone します。

```
$ git clone [url]
Cloning into 'sirokuro-dev7'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
$
```

## Docker

### docker-compose.yml

プロジェクトフォルダの直下に docker-compose.yml を配置します。

```
$ pwd
/Users/c22/Dev/sirokuro-dev7
$ cat docker-compose.yml
version: "3"

services:
  hreact:
    image: node:latest
    container_name: "sirokuro-dev7"
    hostname: "sirokuro-dev7"
    ports:
      - "3007:3000"
    stdin_open: true
    tty: true
    working_dir: "/var/www/html"
    volumes:
      - ./src:/var/www/html
    networks:
      - sirokuronet
networks:
  sirokuronet:
    external: true
$
```

### docker network

network が存在しない場合は docker network create してください。

```
$ docker network ls
NETWORK ID     NAME          DRIVER    SCOPE
b806d26edf5a   bridge        bridge    local
317be678ef27   dumynet       bridge    local
557d49a9a6c7   host          host      local
3f3526a32e99   none          null      local
de546cf034b7   sirokuronet   bridge    local
$
```

### docker-compose up

```
$ docker-compose up
[+] Running 1/1
 ⠿ Container sirokuro-dev7  Created                                                                                                                                  0.1s
Attaching to sirokuro-dev7
sirokuro-dev7  | Welcome to Node.js v18.7.0.
sirokuro-dev7  | Type ".help" for more information.
```

### コンテナでコマンド入力する

```
$ docker container ls
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS                    NAMES
873676d7b4e9   node:latest   "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:3007->3000/tcp   sirokuro-dev7
$ docker container exec -it sirokuro-dev7 /bin/bash
root@sirokuro-dev7:/var/www/html# pwd
/var/www/html
root@sirokuro-dev7:/var/www/html# ls
root@sirokuro-dev7:/var/www/html#
```

## Nextjs + TypeScript

### インストールします

```
root@sirokuro-dev7:/var/www/html# npx create-next-app . --typescript
Creating a new Next.js app in /var/www/html.

Using yarn.

Installing dependencies:
- react
- react-dom
- next

(snip)

Done in 57.19s.

Success! Created html at /var/www/html

root@sirokuro-dev7:/var/www/html# npm list --depth=0
html@0.1.0 /var/www/html
+-- @types/node@18.7.1
+-- @types/react-dom@18.0.6
+-- @types/react@18.0.17
+-- eslint-config-next@12.2.4
+-- eslint@8.21.0
+-- next@12.2.4
+-- react-dom@18.2.0
+-- react@18.2.0
`-- typescript@4.7.4

root@sirokuro-dev7:/var/www/html#
```

### 動作確認

#### ローカルサーバ起動

```
root@sirokuro-dev7:/var/www/html# yarn dev
yarn run v1.22.19
$ next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info  - SWC minify release candidate enabled. https://nextjs.link/swcmin
event - compiled client and server successfully in 3.3s (177 modules)
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry

wait  - compiling / (client and server)...
event - compiled client and server successfully in 579 ms (206 modules)

```

#### ブラウザから確認する

![スクリーンショット 2022-08-12 10.04.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/b3535b0c-63b8-d44f-6aca-94cb45dd93d6.png)

### (参考情報) React 18 から 17 へのダウングレードについて

これまでのインストールにより 2022年8月11日現在だと React 18.2.0 がインストールされました。

その後の技術検証で React 18 環境だと Swiper の autoplay が機能しないことがわかりました。Swiper 公式のデモでは React 17 を使用しており、自力での問題解決もできなかったため React 18 の利用は諦め、以前作成した React 18 -> 17.0.2 へのダウングレードを行った Docker コンテナを使用して開発を再開しました。

### Vercel デプロイ

ここで一度 Vercel にデプロイします。この後は mui のインストールを行うのですが、その前にデプロイしないと、私には解決できなかったビルドエラーが発生してしまいます。このビルドエラーを解決するために試行錯誤したのですが、mui インストール前にビルドしておけばその後のビルドが通るようになるので、とりあえずはこのタイミングでデプロイすることにしています。

#### yarn build

ローカルサーバは control + c で停止します。

```
root@sirokuro-dev7:/var/www/html# yarn build
yarn run v1.22.19
$ next build
info  - SWC minify release candidate enabled. https://nextjs.link/swcmin
info  - Linting and checking validity of types
info  - Creating an optimized production build
info  - Compiled successfully
info  - Collecting page data
info  - Generating static pages (3/3)
info  - Finalizing page optimization

Page                                       Size     First Load JS
┌ ○ /                                      5.42 kB        83.1 kB
├   └ css/ae0e3e027412e072.css             707 B
├   /_app                                  0 B            77.7 kB
├ ○ /404                                   186 B          77.8 kB
└ λ /api/hello                             0 B            77.7 kB
+ First Load JS shared by all              77.7 kB
  ├ chunks/framework-db825bd0b4ae01ef.js   45.7 kB
  ├ chunks/main-f0e16f48d3775e5e.js        30.7 kB
  ├ chunks/pages/_app-deb173bd80cbaa92.js  499 B
  ├ chunks/webpack-7ee66019f7f6d30f.js     755 B
  └ css/ab44ce7add5c3d11.css               247 B

λ  (Server)  server-side renders at runtime (uses getInitialProps or getServerSideProps)
○  (Static)  automatically rendered as static HTML (uses no initial props)

Done in 16.96s.
root@sirokuro-dev7:/var/www/html#
```

yarn start するとプロダクト版が確認できますがここでは省略します。

#### git push

```
$ pwd
/Users/c22/Dev/sirokuro-dev7
$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	docker-compose.yml
	src/

nothing added to commit but untracked files present (use "git add" to track)
$ git add .
$ git commit -m "1st commit"
[main 31cbf7e] 1st commit
 15 files changed, 2139 insertions(+)
 create mode 100644 docker-compose.yml
 create mode 100644 src/.eslintrc.json
 create mode 100644 src/.gitignore
 create mode 100644 src/README.md
 create mode 100644 src/next.config.js
 create mode 100644 src/package.json
 create mode 100644 src/pages/_app.tsx
 create mode 100644 src/pages/api/hello.ts
 create mode 100644 src/pages/index.tsx
 create mode 100644 src/public/favicon.ico
 create mode 100644 src/public/vercel.svg
 create mode 100644 src/styles/Home.module.css
 create mode 100644 src/styles/globals.css
 create mode 100644 src/tsconfig.json
 create mode 100644 src/yarn.lock
$ git push
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 8 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (22/22), 46.98 KiB | 9.40 MiB/s, done.
Total 22 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/unrcom/sirokuro-dev7.git
   4b04753..31cbf7e  main -> main
$
```

#### Vercelデプロイ

- dashboard の右上にある [+ New Project] をクリック

![スクリーンショット 2022-08-12 10.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/93a32172-6822-7d10-dfbf-297215ec42b6.png)

- git push したリポジトリを [Import]

![スクリーンショット 2022-08-12 10.20.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/eef894ed-fd43-209e-7b72-09b4fe55ec39.png)

- FRAMEWORK PRESET には Next.js を指定する
- ROOT DIRECTORY には src を指定する
- [Deploy] をクリック

![スクリーンショット 2022-08-12 10.24.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/77c27853-a54a-43ff-5927-74d07d686f85.png)

紙吹雪が舞えばデプロイは成功です。

#### 動作確認

![スクリーンショット 2022-08-12 10.25.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/50bad850-a4b0-f89e-3e26-f4b5ce69f4f7.png)

- [Go to Dashboard] をクリック
- 次画面の [Visit] をクリックするか DOMAINS の URL でアプリにアクセスできます

![スクリーンショット 2022-08-12 10.29.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/7bea9e7d-782c-a737-57f9-67610fe3c6a7.png)

## mui

### インストールします

以下の ``` yarn add @mui/material @emotion/react @emotion/styled --legacy-peer-deps ``` は React 18 で投入したものです

React 17 の場合は ``` yarn add @mui/material @emotion/react @emotion/styled ``` となります。

```
root@sirokuro-dev7:/var/www/html# yarn add @mui/material @emotion/react @emotion/styled --legacy-peer-deps
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...

(snip)

Done in 31.09s.
root@sirokuro-dev7:/var/www/html#
```

ここも React 17 の場合は ``` yarn add @mui/icons-material ``` です

```
root@sirokuro-dev7:/var/www/html# yarn add @mui/icons-material --legacy-peer-deps
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...```
[3/4] Linking dependencies...

(snip)

Done in 148.73s.
root@sirokuro-dev7:/var/www/html#
```

```
root@sirokuro-dev7:/var/www/html# npm list --depth=0
html@0.1.0 /var/www/html
+-- @emotion/react@11.10.0
+-- @emotion/styled@11.10.0
+-- @mui/icons-material@5.8.4
+-- @mui/material@5.10.0
+-- @types/node@18.7.1
+-- @types/react-dom@18.0.6
+-- @types/react@18.0.17
+-- eslint-config-next@12.2.4
+-- eslint@8.21.0
+-- next@12.2.4
+-- react-dom@18.2.0
+-- react@18.2.0
`-- typescript@4.7.4

root@sirokuro-dev7:/var/www/html#
```

### index.tsx で mui を使ってみる

Grid と Typography を import して main タグと footer のなかを書き換えています。

```
root@sirokuro-dev7:/var/www/html/pages# pwd
/var/www/html/pages
root@sirokuro-dev7:/var/www/html/pages# cat index.tsx
import type { NextPage } from "next";
import Head from "next/head";
import styles from "../styles/Home.module.css";

import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";

const Home: NextPage = () => {
  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}>
        <Grid container spacing={0}>
          <Grid item xs={12} alignItems="center">
            <Typography variant="h3">Welcome to sirokuro.site</Typography>
          </Grid>
        </Grid>
      </main>

      <footer className={styles.footer}>
        <a
          href="https://unremoted.com"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by unremote.com
        </a>
      </footer>
    </div>
  );
};

export default Home;
root@sirokuro-dev7:/var/www/html/pages#
```

yarn dev すると以下が表示されます。

![スクリーンショット 2022-08-12 11.01.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/730035ff-bcdc-336b-7468-e58cbd535a66.png)

### Vercelデプロイ

ここでもデプロイして動作確認しておきます。

![スクリーンショット 2022-08-12 11.10.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/f7faf6e5-3971-5cff-bebb-7d4452da921d.png)

## Supabase

### Create new project 

- [New project]
- organization を選択または [+ New organization] で組織を追加する

![スクリーンショット 2022-08-12 11.19.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/38077c74-6717-19f2-ede1-7ff899e1f4f0.png)

- [Create new project]

少し待つと新しいプロジェクトが整います。

### Vercel に Supabase の接続情報を登録する

Welcome to your new project の画面に Project Configuration URL と Project API key が表示されます。これは Vercel の Setteings -> Environment Variables に登録します。

(Settings -> Environment Variables)

- NAME: NEXT_PUBLIC_SUPABASE_API_KEY
  - VALUE: Welcome to your new projec に表示されている API key
  - [Add] をクリック
- NAME: NEXT_PUBLIC_SUPABASE_URL
  - VALUE: Welcome to your new projec に表示されている URL
  - [Add] をクリック

### Authentication の設定

最低限の設定を入れておきます。Auth Provuders の設定は利用シーンにより異なりますので本Webサービスの場合を示しています。

#### Settings

- [Authentication] -> [Settings]
- Auth Providers で Email をクリック
- 設置内容を確認して変更した場合は [Save] をクリック

#### Email Templates

提供するサービスに応じて変更します。

### データベースの設定

#### Create new table

- [Table editor]
- [Create new table]

作成例としてカテゴリー (cats) テーブルをつくってみます。

![スクリーンショット 2022-08-12 15.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/b4829750-1943-50f5-283b-f5b704f540df.png)

![スクリーンショット 2022-08-12 15.21.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/1687568b-012c-e926-ca1a-a030aaf6ee15.png)

- [Save]

同じ手順で以下のテーブルもつくりました。

- comments
- posts
- profiels
- replies
- votes

### Storage の設定

#### Create a new bucket

ここでは各ユーザが登録するアバター画像を格納するバケットと、投稿画像を格納するバケットをつくっておきます。

- Storage -> New bucket -> [Create a new bucket]

![スクリーンショット 2022-08-12 16.12.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539175/eae27b13-4124-cf1f-7402-f535ecec8957.png)

- [Create bucket]

同じ手順で posts バケットもつくっておきます。

これで RLS (Row Level Security) 以外の設定を入れられたので、Dockerコンテナ側のインストールに戻ります。

## その他のパッケージのインストール

### 8月12日に記載したインストール手順について

昨日 (8月12日) ここに /var/www/html/pages フォルダでパッケージのインストールしていた手順を記載したのですが、その後の動作確認で、/var/www/html でインストールしなければならないことがわかりました。

以下の手順は修正しましたので、問題ありません。

/var/www/html/pages でインストールしてしまった方は yarn remove でパッケージを削除して、/var/www/html で yarn add を実行すると、正常な状態でインストールされましたのでご対応ください。

### supabase-js

```
root@sirokuro-dev7:/var/www/html/pages# yarn add @supabase/supabase-js
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...

(snip)

Done in 28.07s.
root@sirokuro-dev7:/var/www/html/pages#
```

### .env.local

ローカルサーバから supabase への接続情報を指定します。Vercel で Create new project を実行した際に取得した Project Configuration URL と Project API key を指定します。

```
root@sirokuro-dev7:/var/www/html# pwd
/var/www/html
root@sirokuro-dev7:/var/www/html# cat .env.local
NEXT_PUBLIC_SUPABASE_URL=https://xxxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_API_KEY=eyJhbGxxxxxxSSV3s
root@sirokuro-dev7:/var/www/html#
```

### react-query

```
root@sirokuro-dev7:/var/www/html# pwd
/var/www/html
root@sirokuro-dev7:/var/www/html# yarn add react-query
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 11 new dependencies.
info Direct dependencies
└─ react-query@3.39.2
info All dependencies
├─ big-integer@1.6.51
├─ broadcast-channel@3.7.0
├─ detect-node@2.1.0
├─ js-sha3@0.8.0
├─ match-sorter@6.3.1
├─ microseconds@0.2.0
├─ nano-time@1.0.0
├─ oblivious-set@1.0.0
├─ react-query@3.39.2
├─ remove-accents@0.4.2
└─ unload@2.2.0
Done in 6.51s.
root@sirokuro-dev7:/var/www/html#
```

### e.t.c.

```
root@sirokuro-dev7:/var/www/html# yarn add zustand
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ zustand@4.0.0
info All dependencies
└─ zustand@4.0.0
Done in 4.70s.
root@sirokuro-dev7:/var/www/html#
```

```
root@sirokuro-dev7:/var/www/html# yarn add @heroicons/react
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ @heroicons/react@1.0.6
info All dependencies
└─ @heroicons/react@1.0.6
Done in 12.46s.
root@sirokuro-dev7:/var/www/html#
```

```
root@sirokuro-dev7:/var/www/html# yarn add react-error-boundary
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ react-error-boundary@3.1.4
info All dependencies
└─ react-error-boundary@3.1.4
Done in 3.48s.
root@sirokuro-dev7:/var/www/html#
```

```
root@sirokuro-dev7:/var/www/html# yarn add date-fns
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ date-fns@2.29.1
info All dependencies
└─ date-fns@2.29.1
Done in 30.99s.
root@sirokuro-dev7:/var/www/html#
```

## Swiper

カルーセルコントロールです。Swiper を知るまでさまざまなコントールを試して時間を使ってしまいましたが、運よくここに行きつきました。

```
root@sirokuro-dev7:/var/www/html# yarn add swiper
yarn add v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@emotion/react > @emotion/babel-plugin@11.10.0" has unmet peer dependency "@babel/core@^7.0.0".
warning "@emotion/react > @emotion/babel-plugin > @babel/plugin-syntax-jsx@7.18.6" has unmet peer dependency "@babel/core@^7.0.0-0".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 3 new dependencies.
info Direct dependencies
└─ swiper@8.3.2
info All dependencies
├─ dom7@4.0.4
├─ ssr-window@4.0.2
└─ swiper@8.3.2
Done in 7.97s.
root@sirokuro-dev7:/var/www/html#
```

開発環境の構築は以上です。Vercelにデプロイして動作確認に問題がなければ完了です。

## 不足しているモジュールのインストール

2022年8月24日追記

'@mui/x-date-pickers/DatePicker' を使用していましたが、そのインストールに関する記述が不足していました。以下に追記します

- yarn add date-fns
これだけなぜか、上記のインストール手順に含まれていました
- yarn add @date-io/date-fns
- yarn add @mui/x-date-pickers

2022年8月29日追記

react-markdown が必要になったのでインストールしました

- yarn add react-markdown

2022年11月5日追記

クライアントサイドでイメージファイルのリサイズを行うことにしました

これには Browser Image Compression を使ってみようと思います

- yarn add browser-image-compression