💙

[Fortnite] Nextjs14でちょい真面目にユーザー戦績確認アプリを作った🪅[ビクロイ]

2024/01/10に公開

Fortnite って?🔫

フォートナイトは Epic Games から出てる個人的に世界一面白いと思っている神 TPS ゲームです 🔫
詳しくはこちらから 💁
https://www.fortnite.com

成果物 🧢

デモ
https://youtu.be/zrFelQXkzYM?si=5vGk5rsyYQLx2rLN

アプリはこちら 🍀
https://fortnite-victory-royals.vercel.app

https://github.com/tara-is-ok/fortnite-victory-royals

技術スタック 🌱

tech stack
今回メインで使った技術

  • Nextjs
    • App Router, API Routes
  • Tailwind CSS + Material Tailwind
    • プロジェクト後半から Material Tailwind を使用
  • SWR
    • 状態管理
  • ESLint + Prettier
    • 個人開発といえど最低限の品質を保って開発を行う
    • 以前作成したテンプレートが良い感じに使えるかの確認

選定理由は単純に Nextjs14, TailwindCSS を使ってみたかったからです。
こういうことが出来るのも個人開発の良いところだったと感じました!💡

https://zenn.dev/tara_is_ok/articles/75f17beaef6ee8

ディレクトリ構成 🧩

/srcは以下のようにしました!

ディレクトリ 説明 用途
app Nextjs App Router + API Routes URL マッピングを行うページコンポーネント
components UI パーツ ページを横断して使うコンポーネント
hooks アプリ全体で使うカスタム hook API リクエストの隠蔽などのページを横断して使うカスタム Hook
providers アプリ全体のコンテキスト SWR や React.Context などルートでラッピングする必要があるコンポーネント
types アプリ全体で使う型 types/apiには OpenAPI から自動生成される型を配置し基本ここから型を参照し開発を行う。また、types/はドメインごとに独自定義が必要な場合ファイルの作成 ✅
utils アプリ全体で使う便利関数 定数やオブジェクトの整形などの純粋関数。ドメインごとにファイルの作成 ✅

fragments

git リポジトリを見ていただいた方は分かる通り、コンポーネント配下に/fragmentsというディレクトリが存在しています。
/fragmentsコンポーネントやファイル分割のみを行いたい + そのコンポーネントでしか使わない(ページ横断を行わない) パーツ置き場になります。
これは atomic design からコンポーネント設計を行なった際にorganismsに 1 度しか使われないコンポーネントが大量発生する問題に対抗する手段となります。

結果、無意識的にコンポーネントや処理が分割統治され、1 ファイルあたりの記述量が減り可読性が向上するのと、コンポーネントが単一責任となり保守性も上がります。

参考

下記の bulletproof-react を参考にディレクトリ構成を考えました

https://github.com/alan2207/bulletproof-react/blob/master/docs/project-structure.md

機能 💦

Victory Royal(1 位)数の表示

スクショやリンクを送ってただ自慢したかった私個人の超願望 🤹‍♂️

ページ画像

wins

戦績表示

  • ソロ、デュオ、スクワッドの各モードに応じた詳細な戦績を表示する
    • ビクロイ数やキル数、勝率などの表示
ページ画像

stats

API Routes(中間 API)🫥

今回は下記の構成です!
api routes

本体の API を隠蔽

中間 API を挟むことで、外部から本体の API(fortnite api)にアクセスすることを防ぐことでセキュリティの強化を図りました!💎
中間 API を利用せずにリクエストを行なった場合headersの値が外部に見えてしまいます。
今回は Public な API なのであまり効果はないですが、今後開発で使用する場合には役立ちそうだなと感じました!

API エンドポイントの抽象化

フロントエンド ↔️ バックエンドでの API エンドポイントを抽象化を行いました。
今回を例に挙げると、中間 API を使わない場合と使う場合のフロントからのリクエストを次に示します

中間 API なし

export const useStats = () => {
  const { params } = useStatsParams();
  const queryParams = hasUsername(params) && new URLSearchParams(params).toString();
  const { data, error, isLoading } = useSWR<StatsResponse, StatsError>(
    //headerを付与して本体(fortnite-api)に直接リクエスト
    `${apiBaseUrl}/stats/br/v2?${queryParams}`,
    (url: string) =>
      axios(url, {
        headers: { authorization: apiKey },
      }).then((res) => res.data)
  );
  return { data: data?.data, error, isLoading };
};

apiBaseUrlは fortnite-api のエンドポイントです

中間 API あり

1.API Routes を作成する
https://github.com/tara-is-ok/fortnite-victory-royals/blob/main/src/app/api/stats/route.ts

ここで先に header の付与を行う

2. フロントエンドのリクエスト先を API Routes に設定
https://github.com/tara-is-ok/fortnite-victory-royals/blob/main/src/hooks/useStats.ts

API Routes 側で headers などの情報が隠蔽されるため、フロントエンドでは API Routes のエンドポイントを叩くだけで良くなります

参考

こちらの記事を参考にさせていただきました!🎂
https://zenn.dev/sutamac/articles/624aba9a62c52a

背景 🗝️

今回アプリを作成するにあたり大きく分けて 3 つのタイプの動機がありました 🧌

1.モチベ

  • ビクロイ数に応じてエモートを表示させて、そのスクショを撮って友人に自慢したい(煽りたい笑 🪬)
    • または自分の結果がすぐ見れるリンクを送りたい
  • スマホで手軽に確認したい
  • かわいめのデザインでフォートナイトの統計をみたい!(超主観 🫥)

2.使い勝手

  • Discord アカウントを経由している
    • 普段私は Discord を使わないのでアプリを開く習慣がなかった
    • 統計を見るためにチャット上で/command~~と入力が求められることがあり気持ち的なハードルが高い
  • エラー後の UI
    • user(私)がメッセージを見て問題を解決でき、次の操作に進める UI ではなかった
    • epic アカウントの username を入力すべきところに、私が普段 fortnite で使用している playstation の username を入力してしまい統計が見れないなんでや!🧎 なんてことが結構あった

3.技術

以下を使ってみたかった

  • Next.js14
    • App Router
    • API Routes
  • Tailwind CSS
  • 以前作った Nextjs テンプレートがいい感じに動くか

今後の課題 🪡

下記についてアドバイスやコメントいただけるとありがたいです!!🍄

ルート画面(/)遷移時にリクエストがリセットされる

user の状態を React.Context で管理しているのですが、ルート画面遷移時に状態がリセットされる事象に遭遇してハマっています
おそらくこの課題が関連していそうですが、まだ試せていないです。
https://github.com/i18next/next-i18next/issues/2187

Victory Royal(1 位)数の表示 UI のアップデート

開発をしていていくつか UI のアイデアが思いつきました。
以下はその例です。

  • 進撃の巨人のリヴァイやミカサの討伐数とビクロイ(またはキル数)を比較する
  • ビクロイ数とエベレストの標高を比較する
  • など

煽りパターンが 1 パターンでは相手(友人)も煽りに慣れてしまうと思うので、今後は煽りパターンを切り替えるようにしてたくさん煽れるように追加で実装していきたいです 🪼 笑

最後に ❤️‍🔥

今回アプリを作成してみて、私はまだ 200 弱しかビクロイしてないことに気づきました(プレイ歴は 3 年ほど)
これではまだ胸を張って煽るレベルではないので、ゲーム、仕事ともに精進していきます!!!!

Discussion