【個人開発】趣味で作ったWebアプリをNext.js使ってリプレイスしたらページパフォーマンスが90くらいになった話

はじめまして！もんたです。

ちょこっと前に[もんたの森っていう個人開発のWEBアプリケーションをリリースした話](https://qiita.com/Maminumemonta0706/items/9e8632698fb6a8329b8c)をしたんですが、この記事では『そのもんたの森のリプレイス企画を実施したよ〜』って話をしようかと思います。

この記事を読んで僕と同じかけだしエンジニアの個人開発のモチベーションにつながれば幸いです！

あ、そういえばいろいろやらせてもろてます。
よかったら覗いてみてあげてください。

**【たまーに描いた絵をアップする X ( Twitter ) 】**

https://x.com/monta_no_mori

**【最近始めた Instagram 】**

https://www.instagram.com/monta_no_mori/

**【もんたのLINEスタンプ】**

https://store.line.me/stickershop/author/2887587/ja

## 今回作ったやつ

https://www.montanomori.com/

### アプリの概要

これ見たらわかりやすいよ

https://qiita.com/Maminumemonta0706/items/9e8632698fb6a8329b8c#%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E6%A6%82%E8%A6%81

## 背景

時は202x年xx月xx日にまで遡る…

ある時、もんたはもんたの森にてバグを発見し、そのバグ修正をしようとした時だった。

🐶「え？もんたの森のコード汚すぎんか？誰が書いたんやこのコードおい。」

🦊「ねーねーもんた。しかももんたの森を[PageSpeed Insights](https://pagespeed.web.dev/)で計測してみたらパフォーマンスが30だったよ！」

🐶「さ、さ、さ、30…！？それってめちゃくちゃわるいのでは？」

👴『もんたの森のパフォーマンス悪くないか？』

🐶「うるさい！」

👴『ほんとうだからだ！！本当のことを言って何が悪いんだ！！』

🐶「すみません。」

👴『しかもお主は学んだことのアウトプットができておらんぞ。』

🐶「え…？ど、どういうことですか！」

👴『お主はエンジニアとして1年間何を学んだのじゃ。その成果を形にしてみたのか？していないじゃろう。自分の胸に手を当ててみなさい。』

🐶「う、ううぅ…！すみませんおじいさん！実はやらないといけないことはわかっているんです…！で、でもめんどくさくって…！」

👴『本当はわかっておるのじゃろう。自分がこれから何をするべきか。』

🐶「はい！！わかっています…！！」

👴『何をしないといけないのかいってみなさい』

🐶「もんたの森の…！リプレースです！！！」

👴『よういうた！！！』

そしてもんたのもんたの森リプレイス企画が開始したのであった。

---

冗談はさておき。ガチの理由はこちらです。

- もんたの森のPageSpeed Insightsのパフォーマンスが悪い
- Next.jsの勉強をしてみたかった
- 旧もんたの森のディレクトリ構成がわかりずらい
- もんたの森は全体的に読みにくいコードが多い。全体的にコードを読みやすくしたい
- もんたの森をもっと使ってもらえるようなイケイケサービスにしたい



## やったこと話す前にPageSpeed Insightsがどうなったのか
今回のリプレイスのおかげでPageSpeed Insightsのパフォーマンス結果は30から平均90くらいにまで改善されました！！🥳

![スクリーンショット 2024-08-03 23.03.50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038763/b1b85c77-d241-bbf3-e88a-f29d6138d94b.jpeg)

ここから詳細が見れます
https://pagespeed.web.dev/analysis/https-www-montanomori-com/f2b6tw4upx?form_factor=mobile


## 今回のプロジェクトでやったこと

ちなみにですが、プロジェクト管理はNotionを使って行なっていました。
暇な方はこちらをご覧くださいませ。

https://www.notion.so/monta-database/9fe205601ef94ac98a62535a24dbbd96


### 1. デザインをゼロから作り直した

もんたの森のリプレイスプロジェクトでは、もんたの森のデザインを一新させました。

0から[Figma](https://www.figma.com/)でデザインを作成しました。

また、サイトのトップページも0から作成するのは難しいプロセスではあったのですが、試行錯誤しながらもんたの森のデザインを形作っていくプロセスはかなり楽しかったことを覚えています。

トップページを作成することで、旧もんたの森と比べて一気にサイトらしさが出てきた気がして、デザインをしていて楽しかったです。

ちなみに、もんたの森のデザインは以下のサイトを参考に作成しました。

https://hiyokoyarou.com/

https://icons8.jp/icons

https://www.shigureni.com/


#### ユーザー画面デザイン
![スクリーンショット 2024-08-03 20.59.39.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038763/26abd124-d6e0-0332-380a-4cfba5bea264.jpeg)

#### 管理画面デザイン
![スクリーンショット 2024-08-03 20.59.51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038763/b5f7101c-c495-07f5-b122-7f2b2e172bcf.jpeg)

こちらがもんたの森のFigmaファイルです。
暇な方はぜひご覧くださいませ。

https://www.figma.com/design/xzKc1dh8tNqZc624oYdnN0/%E7%9C%9F%E3%83%BB%E3%82%82%E3%82%93%E3%81%9F%E3%81%AE%E6%A3%AE%E3%80%80%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3?node-id=0-1&t=3OMP5VK00xLpMSTT-1

### 2. React→Next.jsのApp Routerを使ってフロントエンドの実装をした

旧もんたの森はReactを使って全てのデータをレンダリング後に取得していました。

そのため、ユーザー画面が表示されてからデータの取得を行い、そのレンダリングを行うためユーザー画面が大きく変わってしまいユーザー体験を損ねているという課題がありました。
（事前に表示スペースを確保しておけば改善できそうではあるけど無視してください）

上記の課題はPageSpeed Insightsによって指摘された内容です。

その課題を解決するためにReact Server Componentを使うためにNext.jsを使ってもんたの森をリプレイスしようと決心しました。
（そのほかにも個人的にNext.jsの勉強したかったってのもあります。）

当初はPage Routerを使ってルーティングの実装しようとしていたのですが、App Routerってのが最近出てきたらしいので、App Routerを使って実装することにしました。

App Routerの理解においてはメインではChatGPTを使って勉強していたのですが、以下のサイトもかなり参考になりました！

https://zenn.dev/yamadadayo123/articles/6cb4f586de0183

https://rakuraku-engineer.com/posts/nextjs-app/



### 3. ディレクトリ構成をわかりやすくした

ぶっちゃけそこまで大きく変化があるわけではないのですが、変更前よりもより細かくディレクトリを分けるようにしました。
わかりにくいかもしれませんが、以下に変更前と変更後のディレクトリ構成を載せています。

もし、「もっとこうしたほうがいいんじゃねぇの」ってご意見ありましたらコメントいただけますと幸いです！🐶

#### 変更前

```
.
├── Makefile
├── client
│   ├── Dockerfile
│   ├── dist
│   ├── index.html
│   └── src
│       ├── App.tsx
│       ├── components
│       ├── main.css
│       ├── main.scss
│       ├── main.tsx
│       ├── pages
│       ├── route.ts
│       └── store.tsx
├── docker-compose.yaml
├── go.mod
├── go.sum
└── server
    ├── Dockerfile
    ├── api
    ├── app.env
    ├── credential.json
    ├── db
    │   ├── Dockerfile
    │   ├── migration
    │   ├── query
    │   └── sqlc
    ├── fly.toml
    ├── main.go
    ├── sqlc.yaml
    ├── token
    └── utils
        ├── config.go
        └── password.go

```

#### 変更後

```
.
├── Makefile                     # ビルドツールの定義
├── client                       # フロントエンド関連ファイル
│   ├── Dockerfile               # クライアント用のDocker設定
│   └── src                      # クライアントソースコード
│       ├── api                  # API呼び出し関連
│       ├── app                  # アプリケーション全体の設定
│       ├── components           # Reactコンポーネント
│       ├── hooks                # カスタムフック
│       ├── middleware.ts        # ミドルウェア設定
│       ├── styles               # スタイルシート
│       ├── types                # TypeScript型定義
│       └── utils                # ユーティリティ関数
├── docker-compose.yml           # Docker Compose設定ファイル
├── server                       # サーバー関連ファイル
│   ├── Dockerfile               # サーバー用のDocker設定
│   ├── api                      # サーバーAPI関連ファイル
│   │   ├── admin                # 管理者用API
│   │   ├── middleware           # ミドルウェア
│   │   ├── user                 # ユーザー用API
│   │   └── router.go            # ルータ設定
│   ├── app.env                  # 環境変数ファイル
│   ├── cmd                      # コマンド関連ファイル
│   │   └── main.go              # メインエントリーポイント
│   ├── credential.json          # 認証情報ファイル
│   ├── fly.toml                 # Fly.io設定ファイル
│   ├── go.mod                   # Goモジュール管理ファイル
│   ├── go.sum                   # Goモジュールのチェックサムファイル
│   ├── internal                 # 内部ライブラリ
│   │   ├── app                  # アプリケーション全体の設定
│   │   ├── db                   # データベース関連ファイル
│   │   └── domains              # ドメインロジック
│   ├── pkg                      # パッケージ
│   │   ├── lib                  # ライブラリ
│   │   ├── token                # トークン管理
│   │   └── util                 # ユーティリティ関数
│   ├── sqlc.yaml                # SQLC設定ファイル
│   └── tmp                      # 一時ファイル
│       ├── build-errors.log     # ビルドエラーログ
│       └── main                 # メイン一時ファイル
└── tools                        # ツール
    └── aggregate_coverage.sh    # カバレッジ集計スクリプト

```

個人的には変更後の方がディレクトリの役割をはっきりさせてファイルを分けたので保守性は高まったなぁと感じております。

### 4. コミットした時にテストコードの結果をPRコメントに表示するようにした

もんたの森では`*_test.go`の形式のgoファイルがコミットされると、自動でテストコードが実行され、テストカバレッジの結果が表示されるようにしています。

![スクリーンショット 2024-08-03 21.20.45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038763/7886bfa4-d501-ba14-c716-ad74edd9cb3e.jpeg)

あんまりやる気が起きないテストコードのモチベーションを高めるためにもこのようにテストコードの結果を表示するのはかなりいいことだなと思います。


## アーキテクチャについて

ここからはもんたの森のアーキテクチャについてご説明していこうかと思います。

エンジニア初心者が作ったものなのでクオリティの低さには目を瞑っていただけますと幸いです。

![Group 252.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2038763/d60e0484-f786-7cc4-5c51-75505061494d.png)


もんたの森の技術スタックは以下になります。

| 技術分野          | 技術スタック              |
|-------------------|---------------------------|
| フロントエンド    | Next.js                   |
| バックエンド      | Golang                    |
| RDBMS             | PostgreSQL                |
| インフラストラクチャー | フロントエンドデプロイ：Vercel <br> バックエンドデプロイ：Fly.io |
| 画像ストレージ    | Google Cloud              |


## もんたの森の今後について

もんたの森の今後について話そうかと思います。

結論としてはインスタグラムやTwitterといったSNSを頑張っていこうかと思います。要はマーケティングです。

これはあくまでもんたの意見なのですが、もんたレベルのラフな絵でもフォロワーが1万人~10万人くらいのアカウントが結構あると思っています。

投稿の内容も特に凝ったものを投稿しているわけではなく、かわいらしい画像をアップし続けている印象のものが多いです。

なので、もんたもそれらのアカウントとなじように絵を描いたらとにかくアップし続けるってのをしようかと思っています。
そこから、もんたの森への導線やLINEスタンプへの導線を作って広告収入やLINEスタンプによる売り上げを作れたらいいなと思っています。

温かい目でもんたの活動を応援していただけますと大変うれしいです。

## おわりに

いかがでしたでしょうか。

今回は個人で開発した「もんたの森」というWebアプリのリプレイス企画についてお話しさせていただきました！

この記事を読んで少しでも個人開発に興味を持ってくれる人が増えたらなと思います！


今後もエンジニアとして学びを続け、多くのユーザーに毎日使われるサービスを開発できればなと思います！

最後までお読みいただきありがとうございました！🐶