🐥

小規模開発のフロントエンド技術選定

2024/12/27に公開

こんにちは。
Spacemarketのエンジニアの8zkです。
クリスマスツリーを買えないままクリスマスを過ごしました。寂しい。来年こそは買えるよう頑張ります!

前提

今回作成したアプリケーションは下記の通りです。

  • 9画面ほどの小規模開発
    • フォーム
    • 検索
    • ユーザー情報 etc...
  • 技術選定を行なうタイミングがBEの技術選定の前(プロジェクトに入るタイミングがフロントエンドの方が早かった)
  • 追加開発を行う想定

採用ライブラリ

採用したライブラリはこちらです。

{
  "dependencies": {
    "@chakra-ui/icons": "^2.1.1",
    "@chakra-ui/react": "^2.8.2",
    "@emotion/react": "^11.11.4",
    "@emotion/styled": "^11.11.5",
    "@hookform/resolvers": "^3.6.0",
    "axios": "^1.7.2",
    "dayjs": "^1.11.11",
    "framer-motion": "^11.2.11",
    "humps": "^2.0.1",
    "next": "14.2.3",
    "react": "^18",
    "react-dom": "^18",
    "react-hook-form": "^7.51.5",
    "swr": "^2.2.5",
    "zod": "^3.23.8"
  },
  "devDependencies": {
    "@babel/preset-react": "^7.24.6",
    "@chakra-ui/cli": "^2.4.1",
    "@chakra-ui/styled-system": "^2.9.2",
    "@testing-library/jest-dom": "^6.4.5",
    "@testing-library/react": "^16.0.0",
    "@testing-library/user-event": "^14.5.2",
    "@types/humps": "^2.0.6",
    "@types/jest": "^29.5.12",
    "@types/lodash.debounce": "^4.0.9",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "eslint": "^8",
    "eslint-config-next": "14.2.3",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "prettier": "^3.3.0",
    "typescript": "^5"
  },
}

Axios

https://axios-http.com/
HTTPリクエストを送るライブラリはAxiosを採用しました。
AxiosもしくはFetch APIの2択になるかと思いますが、Axiosの方が処理が簡単に書けるのと、エラーハンドリングの容易さやインターセプターが使えることのメリットを考えてAxiosを選びました。

REST API × SWR

REST APIはBEの技術選定前にフロントエンドを決めることになったため、その時点ではGraphQLが使えるかわかりませんでした。
なのでGraphQLとRESTを比較してどちらかを決めたというよりBEがどういった技術でも採用可能なREST APIを採用しました。

https://swr.vercel.app/ja
データ取得を簡単にするSWRはプロジェクト内のデータ取得のロジックを単純化してdata, error, isLoading, mutateを提供してくれます。
また、キャッシュ機構を持っているため不要なリクエストを防ぐことができるといったメリットが多く採用しました。

SWRについての学びはこちらのブログにまとめているので覗いていただけると嬉しいです!
https://zenn.dev/spacemarket/articles/b2ba7e5f6e1529
https://zenn.dev/spacemarket/articles/f0fd5dc2ab54a2

Next.js

https://nextjs.org/
フレームワークはNext.jsを採用しました。
SSRもSSGも使っていませんが、昨今のWeb開発のデファクトスタンダードになっており、create-next-appを使うことで簡単にアプリケーションを構築できることなどが採用理由です。

React Hook Form × Zod

フォーム操作とバリデーション管理のライブラリではReact Hook Form と Zod を導入しました。
選定理由はダウンロード数・Star数が多く、軽量であることなどが挙げられますが、一番の決め手は他のプロジェクトで使っておりチームメンバーが学習コストなく触れることでした。

React Hook FormとZodについての学びはこちらのブログにまとめているので覗いていただけると喜びます!
https://zenn.dev/spacemarket/articles/bc087480133dcc

Chakra UI

https://www.chakra-ui.com/
UIライブラリではChakra UIを採用しました。
JSXの中にスタイルを書くことができ、TypeScriptの型を活かすことができます。
こちらも他のプロジェクトで使っていて学習コストがなく使えることが理由で採用しました。

Jest

https://jestjs.io/ja/
テストライブラリにはJestを選定しました。
JestはJavaScriptのテスティングフレームワークです。正直に言えば、選定に絶対的な理由はなく、社内の他のプロジェクトでも多く採用実績があったため採用した次第です。
機会があれば他のテスティングライブラリをちゃんと比較してみたいと思います。

ディレクトリ構成

ディレクトリ構成はfeaturesディレクトリを採用しました。
大体のロジックがfeaturesディレクトリ内に集約しています。
また、featuresの中は特定のドメインに紐づく処理をdomains、ページに紐づく処理をroutesに置きます。

public
├ images
src
├ app
│ ├ page.tsx 
│ ├ layout.tsx
│ └ users
│   ├ page.tsx
│   └ layout.tsx
├ constants
└ features
│   ├ domains
│   │ └ auth
│   │ │ └ components
│   │ │ └ hooks
│   └ routes
│     └ Home
│       ├ components
│       ├ hooks
│       └ index.tsx 
├ helpers
└ hooks
  ├ api
  │ └ useApi.ts
  └ useGetWindowSize.ts

appディレクトリ

ルーティングに関するページのコンポーネントを格納。
appディレクトリをfatにしないためにroutesのコンポーネントを読み込むだけです。

import { Home } from '@/routes/Home';

export default function HomePage() {
  return <Home />;
}

constantsディレクトリ

プロジェクト全体で使う定数の定義を格納。
都道府県の定義などを置きました。

export const PREFECTURES = [
  '北海道',
  '青森県',
  '岩手県',
  '宮城県',
  '秋田県',
  ...
]

features/domainsディレクトリ

特定のドメインに紐づく処理を格納。
例えば認証周りやユーザー情報など特定のドメインに紐づく情報など共通で使われる処理を置きます。
domainsの中でもcomponentsconstantshooksなどディレクトリを分けることによってわかりやすくなります。

features
├ domains
  └ auth
    ├ components
    ├ constants
    └ hooks

features/routesディレクトリ

appと同じページ単位のディレクトリを作成し、そのページだけで使うcomponentshooksなどを格納。
features/domainsディレクトリと同様にcomponentsconstantshooksなどディレクトリを分けることによってわかりやすくなります。

helpersディレクトリ

アプリケーション全体で使う共通の関数を格納。
例えばlocalStorageやライブラリの初期値を設定する処理などを置きます。

hooksディレクトリ

アプリケーション全体で使う汎用的なReact Hooksのコードを格納。
例えば画面のサイズを取得するhooksや、apiをcallするためのhooksなどを置きます。

まとめ

小規模開発ゆえに採用技術はそれほど多くはありませんでした。
しかし、リリースされて実際に使ってくれるユーザーがいるプロダクトのアプリケーションを環境構築したのは初めてで本当に楽しかったです。
この機会をくれた会社には感謝しています!(ごまをすってるわけではありません笑)

さいごに

スペースマーケットでは、一緒にサービスを成長させていく仲間を探しています。
話を聞いてみたい、ちょっとだけ興味がある、などでも大歓迎です!
ご興味ありましたら是非ご連絡ください!

スペースマーケット Engineer Blog

Discussion