React×TypeScriptで作ったポートフォリオサイトを作成した

#はじめに
React、TypeScriptを使った初めての作品として自己紹介サイトを作成しました。

#作成したサイト
https://it-tsumugi.github.io/reactPortfolio/

#実現したいこと
・自分の経歴、能力、作品などが伝わるポートフォリオサイトの作成
・SPAによる高速なページ遷移
・必要な人のみ閲覧してもらえばいいのでSEO対策は考えない
・学習コストが増えすぎるのを防ぐため、サーバーサイドは考慮しなくていい構成にする
・同様の理由で必要以上のフレームワーク、ライブラリを導入しすぎないようにする
・レスポンシブ対応の実装
・チーム開発を意識したコーディングを心掛ける

#使用技術
**フロントエンド**
React, React-Router, React-Hook-Form, EmailJS, TypeScript, styled-component, styled-media-query, Material-UI, react-vertical-timeline-component Yarn, Prettier

**ツール**
Git, GitHub, git-Flow, GitHub-Pages 

個人的に今一番人気があると感じているJavaScriptライブラリであるReactと、今後は新規開発で使われることになりそうなTypeScriptを採用しました。cssライブラリとしてコンポーネント指向と相性の良いstyled-componentsを採用しました。あまりデザインに時間をかけすぎたくなかったのでMaterial-UIも採用しています。ホスティングはGitHub-Pagesで行っています。

#ディレクトリ構成
ディレクトリ構成はcreate-react-appコマンドで作成したプロジェクトディレクトリにatomic designを適用して決めました。organismsやmoluculesは将来的に分割が予想されるコンポーネントも配置しています。コンポーネントを分割する際は再利用性がある場合と可読性の向上のための2つの場合に分けて行いました。


```
reactPortfolio
├── build
├── node_modules
├── package.json
├── public
│   └── index.html
├── README.md
├── src
│   ├── App.tsx
│   ├── assets
│   │   ├── data                           //配列などのデータ格納ディレクトリ
│   │   ├── images                         //画像格納ディレクトリ
│   │   ├── styles
│   │   │   ├── media.tsx                  //styled-media-queryのラッパーファイル
│   │   │   └── theme.tsx                  //Material-UI用のカラーテーマファイル
│   │   └── Type.tsx
│   ├── components
│   │   ├── atoms
│   │   ├── molecules
│   │   ├── organisms
│   │   ├── pages
│   │   └── templates
│   ├── index.tsx
│   ├── react-app-env.d.ts
│   └── ComponentRouter.tsx                 //ルーターファイル
├── tsconfig.json
├── types
│   └── import-jpg.d.ts
└── yarn.lock
```

#コーディング規則
**型定義**
・関数コンポーネントにはアロー関数を使い、型定義は「VFC」で行う。
・childrenを使いたい場合は"PropsType"に型定義して使うこと。
・基本的に関数コンポーネントの返り値に型注釈はつけない。
・anyは使用禁止。

**スタイル**
・一行で済むスタイリングも基本的にはstyled-coponentsでスタイルコンポーネントを作成する。
・スタイルが2行以上に拡張される確率が非常に低いと判断される場合はインラインスタイルを使用してもよい。
・スタイルコンポーネントは関数コンポーネントの後に記述し、登場するスタイルコンポーネントの順に書く
・レスポンシブ対応はstyled-media-queryを用いて行い、レスポンシブ対応しているcssプロパティは下の部分に寄せて改行する。

**命名規則**
・スタイルコンポーネントの名前は"S + キャメルケースの名称"とする。
・複数要素を囲うタグの名前は”意味を推測しやすい名前 + Container”とする。"Wrapper"は混乱を避けるため利用しない。
・コンポーネント全体を囲うタグの名前は”SComponentContainer”とする。
・命名は"Container"などを含めて4単語までのキャメルケースで行い、5単語以上になる場合は1単語を省略するか異なる命名を考える。
・型定義の末尾には"Type"とつける。
・propsの型名は"PropsType"とする。

**その他**
・短絡評価によるコンポーネントの表示、非表示は行わず、三項演算子で実現する。
・importのエリアはライブラリ、material-uiなどのスタイル、自作コンポーネント、型定義や配列データ、に分けて改行を入れる。
・将来的に数が大きくなる可能性がある定数配列などはdataフォルダに格納し、インポートして使う。

#工夫した点
**atomic designによるディレクトリ構成**
atomic designを利用することでコンポーネントがどのように利用されるのかが分かりやすくなり、可読性も向上しました。

**コーディング規則による統一性**
自分以外の人間がコーディングをしたとしても同じようなコーディングになるように自分なりに規則を決めてコーディングしました。

**styled-media-queryを用いたレスポンシブ対応**
そのまま記述することも考えましたが、ブレイクポイントを数値で書くのは非常に危険だと考え、別ファイルに書いてインポートするなども考えましたが少し手間でした。何か良いライブラリがないかと探した際にstyled-media-queryを見つけましたが、そもそもの記述が少し冗長だったのでラップして短く、安全にレスポンシブ対応を行うことが出来ました。今回のポートフォリオではブレイクポイントを1170pxと768pxの２つに設定してレスポンシブ対応を行っています。

```sass
//そのままのstyled-media-query
const SText = styled.h1`
  font-size: 64px;
  ${media.between("medium","large")`
  font-size: 36px;
  `}
  ${media.lessThan("medium")`
  font-size: 26px;
  `}
`;

//ラップして簡略化したもの
const SText = styled.h1`
  font-size: 64px;
  ${media.lg`
  font-size: 36px;
  `}
  ${media.md`
  font-size: 26px;
  `}
`;
```

**簡潔で分かりやすいデザイン**
Material-UIやreact-vertical-timeline-componentを利用した簡潔で分かりやすいデザインを心掛けました。


#反省点
**レスポンシブ対応がモバイルファーストでない**
モバイルファーストで設計した方が良いことは知っていたのですが、具体的にどうすれば良いのかわからずPCをベースにスタイリングしていった結果、あとから大幅な修正をすることになりました。

#おわりに
モダンな技術を用いてポートフォリオサイトを作成しました。作ってみないと分からないことがたくさんあったので良い経験になりました。次はサーバーサイドの技術を含めた作品を作りたいと思います。

#参考文献
https://qiita.com/nerikosans/items/b2f6934347563d9a2587